mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-14 09:15:06 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
996fb54cb0 | ||
|
|
d1e7838cf9 | ||
|
|
a12d2bb4b0 | ||
|
|
60d1a3de3c | ||
|
|
367f9d9161 | ||
|
|
d69fd20a8b | ||
|
|
9493d630a0 | ||
|
|
aee989d23b | ||
|
|
3876218405 | ||
|
|
a6d014a9eb | ||
|
|
52444510d0 | ||
|
|
8840c2109f | ||
|
|
e64a4e7214 | ||
|
|
e46eb46343 | ||
|
|
5da38c9180 | ||
|
|
85bde5827f | ||
|
|
ea2d34589e | ||
|
|
2b46b4f602 | ||
|
|
8e099e9529 | ||
|
|
bbbdc12b2a | ||
|
|
08aa37712f | ||
|
|
ed6dd12db7 | ||
|
|
91e67f8d5d | ||
|
|
9bbb0537ee | ||
|
|
a019b7eed8 | ||
|
|
1772e9eae2 | ||
|
|
17a2ed7f37 | ||
|
|
34ed1d101b | ||
|
|
7cc9cea337 | ||
|
|
6c5e146f96 | ||
|
|
ea50e0a0b6 | ||
|
|
713509a87b | ||
|
|
102c6cad86 | ||
|
|
8af9340be6 | ||
|
|
fc8d3e8b89 | ||
|
|
e84c8c8d7a | ||
|
|
73d61d385c | ||
|
|
69124e3f2f | ||
|
|
98703a11be | ||
|
|
67ca46a220 | ||
|
|
a037a96fa4 | ||
|
|
ed260a34c4 | ||
|
|
e98c927a93 | ||
|
|
b446968e66 |
No files matched your search
@@ -1,14 +1,14 @@
|
||||
# Description of your *PR* and other info
|
||||
<!-- Please include a summary of the change -->
|
||||
## Summary
|
||||
<!-- Briefly describe what this PR changes and why. -->
|
||||
<!-- Any details that you think are important to review this PR? -->
|
||||
<!-- Are there any Issues / PRs related to this one? -->
|
||||
|
||||
<!-- Add a screenshot or a video demonstration for new features -->
|
||||
|
||||
<details open><summary>Template</summary> <!-- OPEN is intentional -->
|
||||
|
||||
### Before submitting a *pull request* make sure you have:
|
||||
- [ ] Read the [AI Contribution Policy](https://github.com/GTNewHorizons/Angelica/blob/master/AI_POLICY.md)
|
||||
- [ ] At least [skimmed](https://github.com/GTNewHorizons/Angelica/search?q=is%3Apr&type=Issues) the tracker for similar pull requests
|
||||
|
||||
</details>
|
||||
## Checklist
|
||||
- [ ] I have tested this PR in DevEnv
|
||||
- [ ] I have tested this PR in Fullpack
|
||||
- [ ] This PR is in compliance with the [GTNH AI Policy](https://github.com/GTNewHorizons/GTNH-Dev-Doc/blob/master/AI_POLICY.md)
|
||||
- [ ] I have at least [skimmed](https://github.com/GTNewHorizons/Angelica/search?q=is%3Apr&type=Issues) the tracker for similar pull requests
|
||||
- [ ] This PR requires another PR in order to merge
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- name: Install a software Vulkan driver
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y xvfb mesa-vulkan-drivers
|
||||
sudo apt-get install -y xvfb mesa-vulkan-drivers libgl1-mesa-dri
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-java@v5
|
||||
with:
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
25
|
||||
- uses: gradle/actions/setup-gradle@v5
|
||||
- name: Run SDL-GPU tests
|
||||
run: xvfb-run -a --server-args="-screen 0 1366x768x24" ./gradlew --build-cache --stacktrace --continue :sdl-gpu:glsmSdlTest :sdl-gpu:sdlGpuDeviceTest
|
||||
run: xvfb-run -a --server-args="-screen 0 1366x768x24" ./gradlew --build-cache --stacktrace --continue :sdl-gpu:glsmSdlTest :sdl-gpu:sdlGpuDeviceTest :lwjgl3-backend:glesTest
|
||||
- name: Check LWJGL did not extract natives to the shared temp dir
|
||||
run: test ! -e "/tmp/lwjgl_$USER"
|
||||
- name: Attach SDL-GPU test results
|
||||
@@ -48,3 +48,6 @@ jobs:
|
||||
sdl-gpu/build/test-results/
|
||||
sdl-gpu/build/reports/tests/
|
||||
sdl-gpu/hs_err_pid*.log
|
||||
lwjgl3-backend/build/test-results/
|
||||
lwjgl3-backend/build/reports/tests/
|
||||
lwjgl3-backend/hs_err_pid*.log
|
||||
@@ -175,8 +175,14 @@ val glsmRedirectAgent: Configuration by configurations.creating {
|
||||
isCanBeResolved = true
|
||||
}
|
||||
|
||||
val glsmMutableStaticsAgent: Configuration by configurations.creating {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
glsmRedirectAgent(project(":glsm", "redirectAgent"))
|
||||
glsmMutableStaticsAgent(project(":glsm", "mutableStaticsAgent"))
|
||||
archScanAsm(libs.asm.tree.test)
|
||||
archScanAsm(libs.asm.commons.test)
|
||||
}
|
||||
@@ -189,6 +195,7 @@ tasks.test {
|
||||
useJUnitPlatform { excludeTags = setOf("gl-core") }
|
||||
configureAngelicaJava8()
|
||||
classpath = archScanAsm + classpath
|
||||
javaAgent(glsmMutableStaticsAgent)
|
||||
jvmArgs("-Dceleritas.lwjglService=org.taumc.celeritas.lwjgl.HeadlessTestLWJGLService")
|
||||
dependsOn(":glsm:classes", ":lwjgl3-backend:classes", ":sdl-gpu:classes")
|
||||
}
|
||||
|
||||
@@ -62,9 +62,10 @@ DependencyHandlerScope.of(dependencies).apply {
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:BetterLoadingScreen:1.7.9-GTNH:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:BetterQuesting:3.8.72-GTNH:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:BuildCraft:7.1.63:dev")
|
||||
compileOnly("com.github.GTNewHorizons:Botania:1.13.32-GTNH:dev") { isTransitive = false }
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:Botania:1.13.32-GTNH:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:LogisticsPipes:1.5.32-GTNH:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:OpenComputers:1.12.55-GTNH:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:OpenComputers:1.12.64-GTNH:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:Mobs-Info:0.5.18-GTNH:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:IguanaTweaksTConstruct:2.7.10:dev")
|
||||
runtimeOnlyNonPublishable("com.github.GTNewHorizons:OpenBlocks:1.12.18-GTNH:dev")
|
||||
@@ -185,6 +186,8 @@ DependencyHandlerScope.of(dependencies).apply {
|
||||
|
||||
compileOnly("mega:fluidlogged-mc1.7.10:0.1.2")
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:LiquidLogged:0.2.0:dev") { isTransitive = false }
|
||||
|
||||
compileOnly("com.cardinalstar.cubicchunks:CubicChunks1710:v0.1.5-alpha:dev") { isTransitive = false }
|
||||
}
|
||||
|
||||
@@ -209,6 +212,7 @@ afterEvaluate {
|
||||
glsmTestFixtures(testFixtures(project(":glsm")) as ModuleDependency) { isTransitive = false }
|
||||
testCompileOnly(testFixtures(project(":glsm")))
|
||||
testImplementation("mega:fluidlogged-mc1.7.10:0.1.2")
|
||||
testImplementation("com.github.GTNewHorizons:LiquidLogged:0.2.0:dev") { isTransitive = false }
|
||||
|
||||
testRuntimeOnly(libs.fastutil)
|
||||
testRuntimeOnly(libs.joml)
|
||||
|
||||
+2
-2
@@ -78,8 +78,8 @@ import java.lang.annotation.Target;
|
||||
* <pre>
|
||||
* @Surround(method = ..., at = @At(value = "INVOKE", target = ...))
|
||||
* private void enter() {
|
||||
* @Surround.Carry("depth") int depth = GLStateManager.pushState(StateSet.BLEND);
|
||||
* @Surround.Carry("prev") int prevProgram = GLStateManager.getActiveProgram();
|
||||
* @Surround.Carry("depth") int depth = GLSMAttribStack.pushState(StateSet.BLEND);
|
||||
* @Surround.Carry("prev") int prevProgram = GLSMPrograms.getActiveProgram();
|
||||
* @Surround.Carry Class<?> prevRenderable = TesrAttribution.currentRenderable;
|
||||
* }
|
||||
*
|
||||
|
||||
@@ -67,6 +67,22 @@ artifacts {
|
||||
}
|
||||
}
|
||||
|
||||
// LWJGL2-API stubs for test JVMs that strip the lwjgl-2 jars (glsmSdlTest, glesTest).
|
||||
val lwjgl2StubsSourceSet = sourceSets.create("lwjgl2Stubs") {
|
||||
java.srcDir("src/lwjgl2Stubs/java")
|
||||
}
|
||||
|
||||
val lwjgl2Stubs by configurations.creating {
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
}
|
||||
|
||||
artifacts {
|
||||
add(lwjgl2Stubs.name, lwjgl2StubsSourceSet.java.classesDirectory) {
|
||||
builtBy(tasks.named("lwjgl2StubsClasses"))
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "Mojang"
|
||||
@@ -111,6 +127,7 @@ val spirvTestRuntime by configurations.creating {
|
||||
dependencies {
|
||||
// MC compile stubs
|
||||
compileOnly(sourceSets["stubs"].output)
|
||||
"lwjgl2StubsCompileOnly"(libs.lwjgl3.opengl)
|
||||
|
||||
// LWJGL
|
||||
compileOnly(libs.lwjgl2)
|
||||
@@ -158,6 +175,7 @@ dependencies {
|
||||
testFixturesApi(platform(libs.junit.bom))
|
||||
testFixturesApi(libs.junit.jupiter.api)
|
||||
testFixturesApi(libs.lwjgl2)
|
||||
testFixturesCompileOnly(libs.asm.tree.test)
|
||||
|
||||
// Test
|
||||
testImplementation(sourceSets["stubs"].output)
|
||||
@@ -257,6 +275,13 @@ fun Test.configureGlsmJava8() {
|
||||
}
|
||||
}
|
||||
|
||||
val mutableStaticsAgentJar by tasks.registering(Jar::class) {
|
||||
archiveClassifier = "mutable-statics-agent"
|
||||
manifest {
|
||||
attributes("Premain-Class" to "com.gtnewhorizons.angelica.glsm.testutil.MutableStatics")
|
||||
}
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform {
|
||||
excludeTags = GL_TASK_TAGS.values.toSet() + "lwjgl3"
|
||||
@@ -265,6 +290,7 @@ tasks.test {
|
||||
excludeTestsMatching("com.gtnewhorizons.angelica.glsm.shader.SpirvShaderTranslator*Test")
|
||||
}
|
||||
configureGlsmJava8()
|
||||
javaAgent(files(mutableStaticsAgentJar))
|
||||
}
|
||||
|
||||
val redirectAgentJar by tasks.registering(Jar::class) {
|
||||
@@ -279,8 +305,14 @@ val redirectAgent by configurations.creating {
|
||||
isCanBeResolved = false
|
||||
}
|
||||
|
||||
val mutableStaticsAgent by configurations.creating {
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
}
|
||||
|
||||
artifacts {
|
||||
add(redirectAgent.name, redirectAgentJar)
|
||||
add(mutableStaticsAgent.name, mutableStaticsAgentJar)
|
||||
}
|
||||
|
||||
val glTestTasks = GL_TASK_TAGS.map { (taskName, tag) ->
|
||||
|
||||
File renamed without changes.
+19
@@ -1,5 +1,7 @@
|
||||
package org.lwjgl.opengl;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class ContextCapabilities {
|
||||
|
||||
public boolean OpenGL30 = true;
|
||||
@@ -21,11 +23,28 @@ public class ContextCapabilities {
|
||||
public boolean GL_ARB_sampler_objects = true;
|
||||
public boolean GL_ARB_shader_image_load_store = true;
|
||||
public boolean GL_ARB_shader_storage_buffer_object = true;
|
||||
public boolean GL_ARB_stencil_texturing = false;
|
||||
public boolean GL_ARB_tessellation_shader = false;
|
||||
public boolean GL_ARB_texture_storage = false;
|
||||
|
||||
public boolean GL_EXT_direct_state_access = false;
|
||||
public boolean GL_EXT_gpu_shader4 = true;
|
||||
public boolean GL_EXT_shader_image_load_store = true;
|
||||
|
||||
public boolean GL_NVX_gpu_memory_info = false;
|
||||
|
||||
public ContextCapabilities() {
|
||||
if ("lwjgl3".equals(System.getProperty("glsm.stubs.capabilities"))) copyFromCurrentContext();
|
||||
}
|
||||
|
||||
private void copyFromCurrentContext() {
|
||||
final GLCapabilities caps = GL.getCapabilities();
|
||||
for (Field field : ContextCapabilities.class.getFields()) {
|
||||
try {
|
||||
field.setBoolean(this, GLCapabilities.class.getField(field.getName()).getBoolean(caps));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new IllegalStateException("LWJGL3 GLCapabilities has no " + field.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,13 @@
|
||||
package org.lwjgl.opengl;
|
||||
|
||||
public final class GLContext {
|
||||
|
||||
private static ContextCapabilities capabilities;
|
||||
|
||||
private GLContext() {}
|
||||
|
||||
public static ContextCapabilities getCapabilities() {
|
||||
if (capabilities == null) capabilities = new ContextCapabilities();
|
||||
return capabilities;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public final class SystemProperties {
|
||||
public static final String GL_PROFILE = System.getProperty("angelica.glProfile", "");
|
||||
public static final boolean DISABLE_NVIDIA_WORKAROUND = Boolean.getBoolean("angelica.disableNvidiaWorkaround");
|
||||
public static final boolean DISABLE_LTW_WORKAROUND = Boolean.getBoolean("angelica.disableLtwWorkaround");
|
||||
public static final boolean EMULATE_CLIP_DISTANCES = Boolean.getBoolean("angelica.emulateClipDistances");
|
||||
|
||||
// Redirector
|
||||
public static final UnmappedGLMode UNMAPPED_GL = parseEnum("angelica.unmappedGL", UnmappedGLMode.WARN, UnmappedGLMode.WARN, UnmappedGLMode.class);
|
||||
@@ -45,6 +46,8 @@ public final class SystemProperties {
|
||||
public static final Boolean TRACY_FINE_ZONES_OVERRIDE = parseBooleanOverride("angelica.tracy.fineZones");
|
||||
public static final String TRACY_DIR = System.getProperty("angelica.tracy.dir", "angelica" + File.separator + "natives" + File.separator + "tracy");
|
||||
public static final Integer TRACY_MAX_SRC_LOCS_OVERRIDE = Integer.getInteger("angelica.tracy.maxSrcLocs");
|
||||
public static final Boolean TRACY_FRAME_IMAGES_OVERRIDE = parseBooleanOverride("angelica.tracy.frameImages");
|
||||
public static final Integer TRACY_FRAME_IMAGE_RATE_OVERRIDE = Integer.getInteger("angelica.tracy.frameImageRate");
|
||||
|
||||
// Profiling
|
||||
public static final String PROFILE_OPTS = System.getProperty("angelica.profile.opts", "event=wall,interval=5ms,alloc=512k,lock=10ms");
|
||||
@@ -63,14 +66,24 @@ public final class SystemProperties {
|
||||
public static final String FLYBY_COMMANDS = System.getProperty("angelica.flyby.commands", "");
|
||||
public static final String FLYBY_ORIGIN = System.getProperty("angelica.flyby.origin", "");
|
||||
public static final Integer FLYBY_DIMENSION = Integer.getInteger("angelica.flyby.dimension");
|
||||
public static final String FLYBY_BIOME = System.getProperty("angelica.flyby.biome", "");
|
||||
public static final boolean FLYBY_SURVIVAL = Boolean.getBoolean("angelica.flyby.survival");
|
||||
public static final FlybyPacing FLYBY_PACING = parseEnum("angelica.flyby.pacing", FlybyPacing.UNCAPPED, FlybyPacing.UNCAPPED, FlybyPacing.class);
|
||||
public static final FlybyWeather FLYBY_WEATHER = parseEnum("angelica.flyby.weather", FlybyWeather.CLEAR, FlybyWeather.CLEAR, FlybyWeather.class);
|
||||
public static final FlybyCamera FLYBY_CAMERA = parseEnum("angelica.flyby.camera", FlybyCamera.FIRST_PERSON, FlybyCamera.FIRST_PERSON, FlybyCamera.class);
|
||||
public static final boolean FLYBY_JFR = Boolean.getBoolean("angelica.flyby.jfr");
|
||||
public static final float FLYBY_PITCH = parseFloat("angelica.flyby.pitch");
|
||||
public static final int FLYBY_SCREENSHOTS = Integer.getInteger("angelica.flyby.screenshots", 0);
|
||||
public static final boolean FLYBY_DEBUG_HUD = Boolean.getBoolean("angelica.flyby.debugHud");
|
||||
public static final Boolean FLYBY_DEBUG_HUD = parseBooleanOverride("angelica.flyby.debugHud");
|
||||
public static final String FLYBY_DEBUG_PROFILE = System.getProperty("angelica.flyby.debugProfile", "");
|
||||
public static final String FLYBY_DEBUG_ENTRIES = System.getProperty("angelica.flyby.debugEntries", "");
|
||||
public static final Boolean FLYBY_DEBUG_FLAT = parseBooleanOverride("angelica.flyby.debugFlat");
|
||||
public static final Boolean FLYBY_HUD_CACHING = parseBooleanOverride("angelica.flyby.hudCaching");
|
||||
public static final Boolean FLYBY_FPS_GRAPH = parseBooleanOverride("angelica.flyby.fpsGraph");
|
||||
public static final boolean FLYBY_DEBUG_DUMP = Boolean.getBoolean("angelica.flyby.debugDump");
|
||||
public static final String FLYBY_CRASH_TEST = System.getProperty("angelica.flyby.crashTest", "");
|
||||
public static final boolean FLYBY_HEAP_CHECK = Boolean.getBoolean("angelica.flyby.heapCheck");
|
||||
public static final int FLYBY_VISITS = Integer.getInteger("angelica.flyby.visits", 1);
|
||||
|
||||
// Debug
|
||||
public static final boolean LWJGL_DEBUG = Boolean.getBoolean("org.lwjgl.util.Debug");
|
||||
|
||||
@@ -25,11 +25,21 @@ public final class CaptureGate {
|
||||
public static final boolean FORCED = SystemProperties.DEBUG_MARKERS || SystemProperties.LWJGL_DEBUG;
|
||||
public static final boolean TOOL_ATTACHED = detectCaptureTool();
|
||||
public static boolean markersThisFrame = true;
|
||||
public static boolean tracyConnected;
|
||||
private static boolean toolAttached = TOOL_ATTACHED;
|
||||
|
||||
private CaptureGate() {}
|
||||
|
||||
public static void refresh() {
|
||||
markersThisFrame = gateValue(FORCED, TOOL_ATTACHED, Tracy.isConnected());
|
||||
tracyConnected = Tracy.isConnected();
|
||||
markersThisFrame = gateValue(FORCED, toolAttached, tracyConnected);
|
||||
}
|
||||
|
||||
static void probeGlTool() {
|
||||
if (RenderSystem.hasExtension("GL_EXT_debug_tool")) {
|
||||
toolAttached = true;
|
||||
LOGGER.info("Capture tool detected via GL_EXT_debug_tool; instrumentation enabled");
|
||||
}
|
||||
}
|
||||
|
||||
static boolean gateValue(boolean forced, boolean toolAttached, boolean tracyConnected) {
|
||||
@@ -37,7 +47,7 @@ public final class CaptureGate {
|
||||
}
|
||||
|
||||
public static boolean enabledAtStartup() {
|
||||
return FORCED || TOOL_ATTACHED;
|
||||
return FORCED || toolAttached;
|
||||
}
|
||||
|
||||
private static boolean detectCaptureTool() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
|
||||
public final class ClipPlaneBooleanState extends BooleanStateStack {
|
||||
@@ -13,12 +14,22 @@ public final class ClipPlaneBooleanState extends BooleanStateStack {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean forwardsToBackend() {
|
||||
return !RenderSystem.isClipDistanceEmulated();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEnabledChanged() {
|
||||
final int before = owner.clipPlaneEnabledMask;
|
||||
if (isEnabled()) {
|
||||
owner.clipPlaneEnabledMask |= (1 << index);
|
||||
} else {
|
||||
owner.clipPlaneEnabledMask &= ~(1 << index);
|
||||
}
|
||||
owner.clipPlaneGeneration++;
|
||||
if ((before == 0) != (owner.clipPlaneEnabledMask == 0) && RenderSystem.isClipDistanceEmulated() && GLSMHooks.CLIP_PLANES_IN_USE.hasListeners()) {
|
||||
GLSMHooks.CLIP_PLANES_IN_USE.post(GLSMHooks.clipPlanesInUseEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.FragmentKey;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.Uniforms;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.FogStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.LightStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ClipPlaneState;
|
||||
@@ -66,7 +68,13 @@ public class CompatUniformManager {
|
||||
static final int LOC_IRIS_MODELVIEW_INVERSE = LOC_MAT_BASE + MAT_FIELDS; // 48
|
||||
static final int LOC_IRIS_PROJECTION_INVERSE = LOC_IRIS_MODELVIEW_INVERSE + 1; // 49
|
||||
|
||||
static final int LOC_COUNT = LOC_IRIS_PROJECTION_INVERSE + 1; // 50
|
||||
static final int LOC_FOG_MODE = LOC_IRIS_PROJECTION_INVERSE + 1; // 50
|
||||
static final int LOC_FOG_PARAMS = LOC_FOG_MODE + 1; // 51
|
||||
static final int LOC_FOG_DISTANCE_MODE = LOC_FOG_PARAMS + 1; // 52
|
||||
|
||||
static final int LOC_MODELVIEW_PROJECTION = LOC_FOG_DISTANCE_MODE + 1; // 53
|
||||
|
||||
static final int LOC_COUNT = LOC_MODELVIEW_PROJECTION + 1; // 54
|
||||
|
||||
private static final String[] LIGHT_FIELD_NAMES = {
|
||||
"ambient", "diffuse", "specular", "position", "halfVector",
|
||||
@@ -84,6 +92,7 @@ public class CompatUniformManager {
|
||||
UNIFORM_NAMES[LOC_MODELVIEW] = "angelica_ModelViewMatrix";
|
||||
UNIFORM_NAMES[LOC_MODELVIEW_INVERSE] = "angelica_ModelViewMatrixInverse";
|
||||
UNIFORM_NAMES[LOC_PROJECTION] = "angelica_ProjectionMatrix";
|
||||
UNIFORM_NAMES[LOC_MODELVIEW_PROJECTION] = "angelica_ModelViewProjectionMatrix";
|
||||
UNIFORM_NAMES[LOC_PROJECTION_INVERSE] = "angelica_ProjectionMatrixInverse";
|
||||
UNIFORM_NAMES[LOC_NORMAL] = "angelica_NormalMatrix";
|
||||
UNIFORM_NAMES[LOC_LIGHTMAP_TEXTURE_MATRIX] = "angelica_LightmapTextureMatrix";
|
||||
@@ -98,6 +107,9 @@ public class CompatUniformManager {
|
||||
UNIFORM_NAMES[LOC_IRIS_TEXTURE_MATRIX] = "iris_TextureMatrix";
|
||||
UNIFORM_NAMES[LOC_IRIS_MODELVIEW_INVERSE] = "iris_ModelViewMatrixInverse";
|
||||
UNIFORM_NAMES[LOC_IRIS_PROJECTION_INVERSE] = "iris_ProjectionMatrixInverse";
|
||||
UNIFORM_NAMES[LOC_FOG_MODE] = "angelica_FogMode";
|
||||
UNIFORM_NAMES[LOC_FOG_PARAMS] = "angelica_FogParams";
|
||||
UNIFORM_NAMES[LOC_FOG_DISTANCE_MODE] = "angelica_FogDistanceMode";
|
||||
UNIFORM_NAMES[LOC_ALPHA_TEST_REF] = "angelica_currentAlphaTest";
|
||||
UNIFORM_NAMES[LOC_SCENE_COLOR] = "angelica_SceneColor";
|
||||
UNIFORM_NAMES[LOC_CLIP_PLANES] = "angelica_ClipPlane[0]";
|
||||
@@ -120,7 +132,14 @@ public class CompatUniformManager {
|
||||
GLContextState owner;
|
||||
int lastMvGen = -1, lastMvLinearGen = -1, lastProjGen = -1, lastTexMatGen = -1;
|
||||
int lastFragmentGen = -1, lastLightingGen = -1, lastClipPlaneGen = -1;
|
||||
ProgramUniforms(int[] locs) { this.locs = locs; }
|
||||
int lastFogMode = -1, lastFogDistanceMode = -1;
|
||||
final boolean lights;
|
||||
ProgramUniforms(int[] locs) {
|
||||
this.locs = locs;
|
||||
boolean any = false;
|
||||
for (int i = LOC_LIGHT_BASE; i < LOC_MAT_BASE; i++) any |= locs[i] != -1;
|
||||
this.lights = any;
|
||||
}
|
||||
}
|
||||
|
||||
// Reusable NIO buffers for upload
|
||||
@@ -186,6 +205,7 @@ public class CompatUniformManager {
|
||||
pu.owner = glCtx;
|
||||
pu.lastMvGen = pu.lastMvLinearGen = pu.lastProjGen = pu.lastTexMatGen = -1;
|
||||
pu.lastFragmentGen = pu.lastLightingGen = pu.lastClipPlaneGen = -1;
|
||||
pu.lastFogMode = pu.lastFogDistanceMode = -1;
|
||||
}
|
||||
|
||||
// Matrix uniforms — skip if this program's storage already holds the current generation
|
||||
@@ -212,12 +232,15 @@ public class CompatUniformManager {
|
||||
uploadFragmentUniforms(locs);
|
||||
}
|
||||
|
||||
pu.lastFogMode = uploadIfChanged(locs[LOC_FOG_MODE], FragmentKey.activeFogMode(glCtx), pu.lastFogMode);
|
||||
pu.lastFogDistanceMode = uploadIfChanged(locs[LOC_FOG_DISTANCE_MODE], glCtx.fogState.getFogDistanceMode(), pu.lastFogDistanceMode);
|
||||
|
||||
// Lighting-derived uniforms (scene color, light sources, material)
|
||||
final int litGen = glCtx.lightingGeneration;
|
||||
if (litGen != pu.lastLightingGen) {
|
||||
pu.lastLightingGen = litGen;
|
||||
if (locs[LOC_SCENE_COLOR] != -1) uploadSceneColor(locs);
|
||||
uploadLightSources(locs);
|
||||
if (pu.lights) uploadLightSources(locs);
|
||||
uploadMaterial(locs);
|
||||
}
|
||||
|
||||
@@ -226,7 +249,7 @@ public class CompatUniformManager {
|
||||
final int cpGen = glCtx.clipPlaneGeneration;
|
||||
if (cpGen != pu.lastClipPlaneGen) {
|
||||
pu.lastClipPlaneGen = cpGen;
|
||||
uploadClipPlanes(locs);
|
||||
uploadClipPlanes(locs, glCtx.clipPlaneEnabledMask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,8 +257,8 @@ public class CompatUniformManager {
|
||||
}
|
||||
|
||||
private static void uploadMatrices(int[] locs, boolean mvChanged, boolean mvLinearChanged, boolean projChanged, boolean texMatChanged) {
|
||||
final Matrix4f mv = GLStateManager.getModelViewMatrix();
|
||||
final Matrix4f proj = GLStateManager.getProjectionMatrix();
|
||||
final Matrix4f mv = GLSMMatrices.getModelViewMatrix();
|
||||
final Matrix4f proj = GLSMMatrices.getProjectionMatrix();
|
||||
|
||||
if (mvChanged) {
|
||||
// ModelView
|
||||
@@ -262,6 +285,11 @@ public class CompatUniformManager {
|
||||
}
|
||||
}
|
||||
|
||||
if ((mvChanged || projChanged) && locs[LOC_MODELVIEW_PROJECTION] != -1) {
|
||||
Uniforms.modelViewProjection(proj, mv, scratchMatrix).get(mat4Buf);
|
||||
RENDER_BACKEND.uniformMatrix4(locs[LOC_MODELVIEW_PROJECTION], false, mat4Buf);
|
||||
}
|
||||
|
||||
if (mvLinearChanged) {
|
||||
// Normal Matrix (inverse-transpose of upper-left 3x3 of ModelView)
|
||||
if (locs[LOC_NORMAL] != -1 || locs[LOC_IRIS_NORMAL] != -1) {
|
||||
@@ -312,21 +340,26 @@ public class CompatUniformManager {
|
||||
|
||||
// angelica_LightmapTextureMatrix — actual GLSM texture unit 1 matrix (set by enableLightmap())
|
||||
if (locs[LOC_LIGHTMAP_TEXTURE_MATRIX] != -1) {
|
||||
GLStateManager.getTextures().getTextureUnitMatrix(1).get(mat4Buf);
|
||||
GLSMTextures.getTextures().getTextureUnitMatrix(1).get(mat4Buf);
|
||||
RENDER_BACKEND.uniformMatrix4(locs[LOC_LIGHTMAP_TEXTURE_MATRIX], false, mat4Buf);
|
||||
}
|
||||
|
||||
// iris_TextureMatrix — texture unit 0 matrix (animated by glints, etc.)
|
||||
if (locs[LOC_IRIS_TEXTURE_MATRIX] != -1) {
|
||||
GLStateManager.getTextures().getTextureUnitMatrix(0).get(mat4Buf);
|
||||
GLSMTextures.getTextures().getTextureUnitMatrix(0).get(mat4Buf);
|
||||
RENDER_BACKEND.uniformMatrix4(locs[LOC_IRIS_TEXTURE_MATRIX], false, mat4Buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int uploadIfChanged(int location, int value, int last) {
|
||||
if (location != -1 && value != last) RENDER_BACKEND.uniform1i(location, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static void uploadFragmentUniforms(int[] locs) {
|
||||
// Fog uniforms
|
||||
FogStateStack fog = GLStateManager.getFogState();
|
||||
FogStateStack fog = GLSMFog.getFogState();
|
||||
if (locs[LOC_FOG_DENSITY] != -1) {
|
||||
RENDER_BACKEND.uniform1f(locs[LOC_FOG_DENSITY], Math.max(0.0f, fog.getDensity()));
|
||||
}
|
||||
@@ -336,6 +369,9 @@ public class CompatUniformManager {
|
||||
if (locs[LOC_FOG_END] != -1) {
|
||||
RENDER_BACKEND.uniform1f(locs[LOC_FOG_END], fog.getEnd());
|
||||
}
|
||||
if (locs[LOC_FOG_PARAMS] != -1) {
|
||||
RENDER_BACKEND.uniform4f(locs[LOC_FOG_PARAMS], fog.linearScale(), fog.linearBias(), fog.expScale(), fog.exp2Scale());
|
||||
}
|
||||
if (locs[LOC_FOG_COLOR] != -1) {
|
||||
vec4Buf.clear();
|
||||
vec4Buf.put((float) fog.getFogColor().x).put((float) fog.getFogColor().y).put((float) fog.getFogColor().z).put(fog.getFogAlpha());
|
||||
@@ -347,10 +383,10 @@ public class CompatUniformManager {
|
||||
// Return -1.0f for ALWAYS or disabled so `alpha <= ref` never discards.
|
||||
if (locs[LOC_ALPHA_TEST_REF] != -1) {
|
||||
final float ref;
|
||||
if (!GLStateManager.getAlphaTest().isEnabled() || GLStateManager.getAlphaState().getFunction() == GL11.GL_ALWAYS) {
|
||||
if (!GLSMDepthStencilAlpha.getAlphaTest().isEnabled() || GLSMDepthStencilAlpha.getAlphaState().getFunction() == GL11.GL_ALWAYS) {
|
||||
ref = -1.0f;
|
||||
} else {
|
||||
ref = GLStateManager.getAlphaState().getReference();
|
||||
ref = GLSMDepthStencilAlpha.getAlphaState().getReference();
|
||||
}
|
||||
RENDER_BACKEND.uniform1f(locs[LOC_ALPHA_TEST_REF], ref);
|
||||
}
|
||||
@@ -360,8 +396,8 @@ public class CompatUniformManager {
|
||||
* Scene color = emission + ambient * lightModel.ambient, alpha = diffuse.a Same computation as {@code Uniforms.uploadLightingPreComputed()}.
|
||||
*/
|
||||
private static void uploadSceneColor(int[] locs) {
|
||||
final MaterialState mat = GLStateManager.getFrontMaterial();
|
||||
final LightModelState lm = GLStateManager.getLightModel();
|
||||
final MaterialState mat = GLSMLighting.getFrontMaterial();
|
||||
final LightModelState lm = GLSMLighting.getLightModel();
|
||||
vec4Buf.clear();
|
||||
vec4Buf.put(mat.emission.x + mat.ambient.x * lm.ambient.x)
|
||||
.put(mat.emission.y + mat.ambient.y * lm.ambient.y)
|
||||
@@ -372,9 +408,7 @@ public class CompatUniformManager {
|
||||
}
|
||||
|
||||
private static void uploadLightSources(int[] locs) {
|
||||
// Early exit: if the first light field isn't present, no lighting uniforms exist
|
||||
if (locs[LOC_LIGHT_BASE] == -1) return;
|
||||
final LightStateStack[] lights = GLStateManager.getLightDataStates();
|
||||
final LightStateStack[] lights = GLSMLighting.getLightDataStates();
|
||||
for (int li = 0; li < 2; li++) {
|
||||
final int base = LOC_LIGHT_BASE + li * LIGHT_FIELDS;
|
||||
final LightState light = lights[li];
|
||||
@@ -421,7 +455,7 @@ public class CompatUniformManager {
|
||||
private static void uploadMaterial(int[] locs) {
|
||||
// Early exit: if the first material field isn't present, no material uniforms exist
|
||||
if (locs[LOC_MAT_BASE] == -1) return;
|
||||
final MaterialState mat = GLStateManager.getFrontMaterial();
|
||||
final MaterialState mat = GLSMLighting.getFrontMaterial();
|
||||
if (locs[LOC_MAT_BASE + MF_EMISSION] != -1)
|
||||
RENDER_BACKEND.uniform4f(locs[LOC_MAT_BASE + MF_EMISSION], mat.emission.x, mat.emission.y, mat.emission.z, mat.emission.w);
|
||||
if (locs[LOC_MAT_BASE + MF_AMBIENT] != -1)
|
||||
@@ -434,16 +468,14 @@ public class CompatUniformManager {
|
||||
RENDER_BACKEND.uniform1f(locs[LOC_MAT_BASE + MF_SHININESS], mat.shininess);
|
||||
}
|
||||
|
||||
private static void uploadClipPlanes(int[] locs) {
|
||||
private static void uploadClipPlanes(int[] locs, int enabledMask) {
|
||||
if (locs[LOC_CLIP_PLANES_ENABLED] != -1) {
|
||||
RENDER_BACKEND.uniform1i(locs[LOC_CLIP_PLANES_ENABLED], GLStateManager.anyClipPlaneEnabled() ? 1 : 0);
|
||||
RENDER_BACKEND.uniform1i(locs[LOC_CLIP_PLANES_ENABLED], enabledMask != 0 ? 1 : 0);
|
||||
}
|
||||
if (locs[LOC_CLIP_PLANES] != -1) {
|
||||
final ClipPlaneState cps = GLStateManager.getClipPlaneState();
|
||||
final ClipPlaneState cps = GLSMRasterizer.getClipPlaneState();
|
||||
clipPlaneBuf.clear();
|
||||
for (int i = 0; i < GLStateManager.MAX_CLIP_PLANES; i++) {
|
||||
cps.putEyePlane(i, clipPlaneBuf);
|
||||
}
|
||||
cps.putEffectivePlanes(enabledMask, clipPlaneBuf);
|
||||
clipPlaneBuf.flip();
|
||||
RENDER_BACKEND.uniform4(locs[LOC_CLIP_PLANES], clipPlaneBuf);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
/*
|
||||
* Ported from Mesa's util_idalloc (src/util/u_idalloc.c).
|
||||
* Ported from Mesa's util_idalloc and util_idalloc_sparse (src/util/u_idalloc.c).
|
||||
*
|
||||
* Original copyright and license:
|
||||
*
|
||||
@@ -32,17 +32,15 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Bitmap ID allocator for display list IDs.
|
||||
*
|
||||
* <p>Bitmap-based: each bit in the {@code data} array represents one ID.
|
||||
* Bit set = allocated, bit clear = free. ID 0 is reserved (never returned).
|
||||
* Sparse bitmap ID allocator for display list IDs; ID 0 is reserved (never returned).
|
||||
*/
|
||||
public class DisplayListIDAllocator {
|
||||
|
||||
private int[] data;
|
||||
private int numElements; // number of uint32 words allocated
|
||||
private int numSetElements; // highest word index with any bit set + 1
|
||||
private int lowestFreeIdx; // optimization: skip fully-allocated words
|
||||
private static final int SEGMENT_SHIFT = 22;
|
||||
private static final int SEGMENT_MASK = (1 << SEGMENT_SHIFT) - 1;
|
||||
private static final int WORDS_PER_SEGMENT = (1 << SEGMENT_SHIFT) / 32;
|
||||
|
||||
private final Segment[] segments = new Segment[512];
|
||||
|
||||
public DisplayListIDAllocator() {
|
||||
this(32); // 1024 IDs initially
|
||||
@@ -50,138 +48,191 @@ public class DisplayListIDAllocator {
|
||||
|
||||
public DisplayListIDAllocator(int initialWords) {
|
||||
if (initialWords < 1) initialWords = 1;
|
||||
this.data = new int[initialWords];
|
||||
this.numElements = initialWords;
|
||||
this.numSetElements = 0;
|
||||
this.lowestFreeIdx = 0;
|
||||
final Segment first = new Segment(initialWords);
|
||||
// Reserve ID 0 (never returned), matching Mesa's skip_zero pattern
|
||||
data[0] = 1;
|
||||
numSetElements = 1;
|
||||
first.data[0] = 1;
|
||||
first.numSetElements = 1;
|
||||
segments[0] = first;
|
||||
}
|
||||
|
||||
private Segment segment(int index) {
|
||||
Segment s = segments[index];
|
||||
if (s == null) {
|
||||
s = new Segment(1);
|
||||
segments[index] = s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public synchronized int allocRange(int count) {
|
||||
if (count <= 0) throw new IllegalArgumentException("count must be > 0");
|
||||
if (count == 1) return allocSingle();
|
||||
return allocMultiple(count);
|
||||
}
|
||||
|
||||
private int allocSingle() {
|
||||
for (int i = lowestFreeIdx; i < numElements; i++) {
|
||||
if (data[i] == 0xFFFFFFFF) continue;
|
||||
|
||||
int bit = Integer.numberOfTrailingZeros(~data[i]);
|
||||
data[i] |= 1 << bit;
|
||||
lowestFreeIdx = i;
|
||||
numSetElements = Math.max(numSetElements, i + 1);
|
||||
return i * 32 + bit;
|
||||
}
|
||||
|
||||
// No slots available, grow. Record old end, then mark first bit there.
|
||||
int oldNumElements = numElements;
|
||||
resize(Math.max(numElements, 1) * 2);
|
||||
lowestFreeIdx = oldNumElements;
|
||||
data[oldNumElements] |= 1;
|
||||
numSetElements = Math.max(numSetElements, oldNumElements + 1);
|
||||
return oldNumElements * 32;
|
||||
}
|
||||
|
||||
private int allocMultiple(int num) {
|
||||
int numWords = divRoundUp(num, 32);
|
||||
int base = findFreeBlock(lowestFreeIdx);
|
||||
boolean found = false;
|
||||
|
||||
while (!found) {
|
||||
int i;
|
||||
for (i = base; i < numElements && i - base < numWords && data[i] == 0; i++)
|
||||
;
|
||||
|
||||
if (i - base == numWords) {
|
||||
found = true;
|
||||
} else if (i == numElements) {
|
||||
// Hit end — base is valid: data[base..end] are zero, resize extends the run into newly zeroed words.
|
||||
resize(numElements * 2 + numWords);
|
||||
found = true;
|
||||
} else {
|
||||
// Non-zero word at i, skip past it
|
||||
base = i + 1;
|
||||
if (count == 1) {
|
||||
for (int i = 0; i < segments.length; i++) {
|
||||
final Segment s = segment(i);
|
||||
if (s.lowestFreeIdx < WORDS_PER_SEGMENT) return (i << SEGMENT_SHIFT) | s.allocSingle();
|
||||
}
|
||||
throw new IllegalStateException("all display list IDs are in use");
|
||||
}
|
||||
|
||||
// Mark bits as used
|
||||
int fullWords = num / 32;
|
||||
int remainder = num % 32;
|
||||
for (int i = base; i < base + fullWords; i++) {
|
||||
data[i] = 0xFFFFFFFF;
|
||||
final int numWords = Segment.divRoundUp(count, 32);
|
||||
for (int i = 0; i < segments.length; i++) {
|
||||
final Segment s = segment(i);
|
||||
if (s.lowestFreeIdx + numWords > WORDS_PER_SEGMENT) continue;
|
||||
final int base = s.allocMultiple(count);
|
||||
if (base + count <= 1 << SEGMENT_SHIFT) return (i << SEGMENT_SHIFT) | base;
|
||||
for (int j = 0; j < count; j++) s.free(base + j);
|
||||
}
|
||||
if (remainder != 0) {
|
||||
data[base + fullWords] |= (1 << remainder) - 1;
|
||||
}
|
||||
|
||||
if (lowestFreeIdx == base) {
|
||||
lowestFreeIdx = base + num / 32;
|
||||
}
|
||||
numSetElements = Math.max(numSetElements, base + numWords);
|
||||
|
||||
return base * 32;
|
||||
throw new IllegalStateException("no free consecutive range of " + count + " display list IDs");
|
||||
}
|
||||
|
||||
private int findFreeBlock(int start) {
|
||||
for (int i = start; i < numElements; i++) {
|
||||
if (data[i] == 0) return i;
|
||||
}
|
||||
return numElements;
|
||||
public synchronized void reserve(int id) {
|
||||
if (id <= 0) return;
|
||||
segment(id >>> SEGMENT_SHIFT).reserve(id & SEGMENT_MASK);
|
||||
}
|
||||
|
||||
public synchronized void free(int id) {
|
||||
if (id <= 0) return; // ID 0 is reserved
|
||||
int idx = id / 32;
|
||||
if (idx >= numElements) return;
|
||||
|
||||
lowestFreeIdx = Math.min(idx, lowestFreeIdx);
|
||||
data[idx] &= ~(1 << (id % 32));
|
||||
|
||||
if (numSetElements == idx + 1) {
|
||||
while (numSetElements > 0 && data[numSetElements - 1] == 0) {
|
||||
numSetElements--;
|
||||
}
|
||||
}
|
||||
final Segment s = segments[id >>> SEGMENT_SHIFT];
|
||||
if (s != null) s.free(id & SEGMENT_MASK);
|
||||
}
|
||||
|
||||
public synchronized void freeRange(int base, int count) {
|
||||
if (count <= 0 || base <= 0) return;
|
||||
|
||||
int startIdx = base / 32;
|
||||
if (startIdx >= numElements) return;
|
||||
|
||||
int end = base + count;
|
||||
for (int id = base; id < end; id++) {
|
||||
int idx = id / 32;
|
||||
if (idx >= numElements) break;
|
||||
data[idx] &= ~(1 << (id % 32));
|
||||
}
|
||||
|
||||
lowestFreeIdx = Math.min(startIdx, lowestFreeIdx);
|
||||
while (numSetElements > 0 && data[numSetElements - 1] == 0) {
|
||||
numSetElements--;
|
||||
final long last = Math.min((long) base + count - 1, Integer.MAX_VALUE);
|
||||
long id = base;
|
||||
while (id <= last) {
|
||||
final int index = (int) (id >>> SEGMENT_SHIFT);
|
||||
final Segment s = segments[index];
|
||||
if (s == null || (id & SEGMENT_MASK) >= (long) s.numElements * 32) {
|
||||
id = (long) (index + 1) << SEGMENT_SHIFT;
|
||||
continue;
|
||||
}
|
||||
s.free((int) id & SEGMENT_MASK);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean isAllocated(int id) {
|
||||
if (id <= 0) return false;
|
||||
int idx = id / 32;
|
||||
if (idx >= numSetElements) return false;
|
||||
return (data[idx] & (1 << (id % 32))) != 0;
|
||||
final Segment s = segments[id >>> SEGMENT_SHIFT];
|
||||
return s != null && s.isAllocated(id & SEGMENT_MASK);
|
||||
}
|
||||
|
||||
private void resize(int newNumElements) {
|
||||
if (newNumElements <= numElements) return;
|
||||
int[] newData = new int[newNumElements];
|
||||
System.arraycopy(data, 0, newData, 0, numElements);
|
||||
data = newData;
|
||||
numElements = newNumElements;
|
||||
}
|
||||
private static final class Segment {
|
||||
private int[] data;
|
||||
private int numElements; // number of uint32 words allocated
|
||||
private int numSetElements; // highest word index with any bit set + 1
|
||||
private int lowestFreeIdx; // optimization: skip fully-allocated words
|
||||
|
||||
private static int divRoundUp(int a, int b) {
|
||||
return (a + b - 1) / b;
|
||||
Segment(int initialWords) {
|
||||
this.data = new int[initialWords];
|
||||
this.numElements = initialWords;
|
||||
}
|
||||
|
||||
int allocSingle() {
|
||||
for (int i = lowestFreeIdx; i < numElements; i++) {
|
||||
if (data[i] == 0xFFFFFFFF) continue;
|
||||
|
||||
int bit = Integer.numberOfTrailingZeros(~data[i]);
|
||||
data[i] |= 1 << bit;
|
||||
lowestFreeIdx = i;
|
||||
numSetElements = Math.max(numSetElements, i + 1);
|
||||
return i * 32 + bit;
|
||||
}
|
||||
|
||||
// No slots available, grow. Record old end, then mark first bit there.
|
||||
int oldNumElements = numElements;
|
||||
resize(Math.max(numElements, 1) * 2);
|
||||
lowestFreeIdx = oldNumElements;
|
||||
data[oldNumElements] |= 1;
|
||||
numSetElements = Math.max(numSetElements, oldNumElements + 1);
|
||||
return oldNumElements * 32;
|
||||
}
|
||||
|
||||
int allocMultiple(int num) {
|
||||
int numWords = divRoundUp(num, 32);
|
||||
int base = findFreeBlock(lowestFreeIdx);
|
||||
boolean found = false;
|
||||
|
||||
while (!found) {
|
||||
int i;
|
||||
for (i = base; i < numElements && i - base < numWords && data[i] == 0; i++)
|
||||
;
|
||||
|
||||
if (i - base == numWords) {
|
||||
found = true;
|
||||
} else if (i == numElements) {
|
||||
// Hit end — base is valid: data[base..end] are zero, resize extends the run into newly zeroed words.
|
||||
resize(numElements * 2 + numWords);
|
||||
found = true;
|
||||
} else {
|
||||
// Non-zero word at i, skip past it
|
||||
base = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark bits as used
|
||||
int fullWords = num / 32;
|
||||
int remainder = num % 32;
|
||||
for (int i = base; i < base + fullWords; i++) {
|
||||
data[i] = 0xFFFFFFFF;
|
||||
}
|
||||
if (remainder != 0) {
|
||||
data[base + fullWords] |= (1 << remainder) - 1;
|
||||
}
|
||||
|
||||
if (lowestFreeIdx == base) {
|
||||
lowestFreeIdx = base + num / 32;
|
||||
}
|
||||
numSetElements = Math.max(numSetElements, base + numWords);
|
||||
|
||||
return base * 32;
|
||||
}
|
||||
|
||||
int findFreeBlock(int start) {
|
||||
for (int i = start; i < numElements; i++) {
|
||||
if (data[i] == 0) return i;
|
||||
}
|
||||
return numElements;
|
||||
}
|
||||
|
||||
void free(int id) {
|
||||
int idx = id / 32;
|
||||
if (idx >= numElements) return;
|
||||
|
||||
lowestFreeIdx = Math.min(idx, lowestFreeIdx);
|
||||
data[idx] &= ~(1 << (id % 32));
|
||||
|
||||
if (numSetElements == idx + 1) {
|
||||
while (numSetElements > 0 && data[numSetElements - 1] == 0) {
|
||||
numSetElements--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAllocated(int id) {
|
||||
int idx = id / 32;
|
||||
if (idx >= numSetElements) return false;
|
||||
return (data[idx] & (1 << (id % 32))) != 0;
|
||||
}
|
||||
|
||||
void reserve(int id) {
|
||||
final int idx = id / 32;
|
||||
if (idx >= numElements) resize((idx + 1) * 2);
|
||||
data[idx] |= 1 << (id % 32);
|
||||
numSetElements = Math.max(numSetElements, idx + 1);
|
||||
}
|
||||
|
||||
private void resize(int newNumElements) {
|
||||
if (newNumElements <= numElements) return;
|
||||
int[] newData = new int[newNumElements];
|
||||
System.arraycopy(data, 0, newData, 0, numElements);
|
||||
data = newData;
|
||||
numElements = newNumElements;
|
||||
}
|
||||
|
||||
private static int divRoundUp(int a, int b) {
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ public class DisplayListManager {
|
||||
private static int glListMode = 0;
|
||||
private static int glListId = -1;
|
||||
private static int recordedStatePushes;
|
||||
private static final DisplayListCommand POP_STATE = GLStateManager::popState;
|
||||
private static final DisplayListCommand POP_STATE = GLSMAttribStack::popState;
|
||||
private static CommandRecorder currentRecorder = null; // Command recorder (null when not recording)
|
||||
private static volatile Thread recordingThread = null; // Thread that started recording (for thread-safety)
|
||||
private static List<AccumulatedDraw> accumulatedDraws = null; // Accumulates quad draws for batching
|
||||
@@ -237,7 +237,7 @@ public class DisplayListManager {
|
||||
currentRecorder.writeMultMatrix(pending);
|
||||
}
|
||||
if (glListMode == GL11.GL_COMPILE_AND_EXECUTE) {
|
||||
GLStateManager.applyMultMatrix(pending);
|
||||
GLSMMatrices.applyMultMatrix(pending);
|
||||
}
|
||||
|
||||
|
||||
@@ -722,7 +722,7 @@ public class DisplayListManager {
|
||||
|
||||
/**
|
||||
* Add an immediate mode draw to the current display list compilation.
|
||||
* Called by GLStateManager.glEnd() when immediate mode geometry is ready.
|
||||
* Called by GLSMDraws.glEnd() when immediate mode geometry is ready.
|
||||
*
|
||||
* <p>This method captures the current transform and command position, creating
|
||||
* an AccumulatedDraw that will be interleaved correctly with other commands
|
||||
@@ -781,7 +781,7 @@ public class DisplayListManager {
|
||||
|
||||
/**
|
||||
* Update the relative transform with a matrix multiplication during display list compilation.
|
||||
* Called by GLStateManager.glMultMatrix().
|
||||
* Called by GLSMMatrices.glMultMatrix().
|
||||
*
|
||||
* <p>In normal mode: accumulates transforms, emits collapsed MultMatrix at barriers.
|
||||
* <p>In debug mode: emits MultMatrix immediately (no collapsing).
|
||||
@@ -833,7 +833,7 @@ public class DisplayListManager {
|
||||
|
||||
/**
|
||||
* Reset the relative transform to identity during display list compilation.
|
||||
* Called by GLStateManager.glLoadMatrix() - after loading an absolute matrix,
|
||||
* Called by GLSMMatrices.glLoadMatrix() - after loading an absolute matrix,
|
||||
* subsequent transforms are relative to that loaded matrix (i.e., start from identity).
|
||||
*/
|
||||
static void resetRelativeTransform() {
|
||||
@@ -1046,9 +1046,12 @@ public class DisplayListManager {
|
||||
}
|
||||
final boolean locked = GLStateManager.acquireDrawLock();
|
||||
try {
|
||||
final CompiledDisplayList previous = displayListCache.put(glListId, compiled);
|
||||
if (previous != null && previous != CompiledDisplayList.EMPTY && previous != compiled) {
|
||||
previous.delete();
|
||||
synchronized (GLSMDraws.displayListIdAllocator) {
|
||||
final CompiledDisplayList previous = displayListCache.put(glListId, compiled);
|
||||
if (previous != null && previous != CompiledDisplayList.EMPTY && previous != compiled) {
|
||||
previous.delete();
|
||||
}
|
||||
GLSMDraws.displayListIdAllocator.reserve(glListId);
|
||||
}
|
||||
} finally {
|
||||
if (locked) GLStateManager.releaseDrawLock();
|
||||
@@ -1147,7 +1150,7 @@ public class DisplayListManager {
|
||||
}
|
||||
if (pendingDraw.drawMode != tessellator.drawMode
|
||||
|| pendingDraw.format != tessellator.getVertexFormat()
|
||||
|| GLStateManager.isContinuousDraw(tessellator.drawMode)
|
||||
|| GLSMDraws.isContinuousDraw(tessellator.drawMode)
|
||||
) {
|
||||
drawBarrier();
|
||||
createNewDraw(tessellator, copyLast);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.states.AlphaState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.BlendState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.Color4;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ColorMask;
|
||||
import com.gtnewhorizons.angelica.glsm.states.MaterialState;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public final class ExitState {
|
||||
public static final int POLYGON_OFFSET_ENABLE_WRITTEN = 1;
|
||||
public static final int POLYGON_OFFSET_VALUES_WRITTEN = 2;
|
||||
final Values entry = new Values();
|
||||
final Values value = new Values();
|
||||
final MaterialState frontMaterial = new MaterialState(GL11.GL_FRONT);
|
||||
final MaterialState backMaterial = new MaterialState(GL11.GL_BACK);
|
||||
long writes, dependencies;
|
||||
boolean valid;
|
||||
int textureDeleteCount;
|
||||
|
||||
public void clear() {
|
||||
valid = false;
|
||||
writes = dependencies = 0;
|
||||
}
|
||||
|
||||
static final class Values {
|
||||
final Color4 color = new Color4();
|
||||
final Vector3f normal = new Vector3f();
|
||||
final Vector4f texCoord = new Vector4f();
|
||||
final Vector4f shaderColor = new Vector4f();
|
||||
final Vector4f overlayColor = new Vector4f();
|
||||
final BlendState blend = new BlendState();
|
||||
final AlphaState alpha = new AlphaState();
|
||||
final ColorMask colorMask = new ColorMask();
|
||||
final Matrix4f textureMatrix = new Matrix4f();
|
||||
long enabled;
|
||||
int activeUnit, clientActiveUnit, matrixMode, texture, depthFunction, cullFace, frontFace, shadeModel;
|
||||
int materialFace, materialParameter;
|
||||
boolean depthMask;
|
||||
float lightmapX, lightmapY, offsetFactor, offsetUnits, offsetClamp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,597 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.BatchStateGuard;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredAlphaHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.CowStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.MaterialState;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfo;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2LongOpenHashMap;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fStack;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Records the GL state a block of rendering code leaves behind, so a later run of the same block can be skipped and
|
||||
* its exit state applied instead.
|
||||
*/
|
||||
final class ExitStateCapture {
|
||||
// Fields 0..12 are the capabilities, in CAPS order. FRONT_* and BACK_* are four contiguous fields each, ordered like
|
||||
// vector(): apply() and finish() address them as 15L << FRONT_AMBIENT and (field - FRONT_AMBIENT) & 3.
|
||||
static final int BLEND = 0, ALPHA = 1, DEPTH = 2, CULL = 3, LIGHTING = 4, NORMALIZE = 5, RESCALE = 6, LIGHT0 = 7, LIGHT1 = 8, TEXTURE0 = 9, TEXTURE1 = 10, OFFSET = 11, COLOR_MATERIAL = 12, COLOR = 13, NORMAL = 14, TEXCOORD = 15,
|
||||
LIGHTMAP = 16, SHADER_COLOR = 17, BLEND_FUNC = 18, ALPHA_FUNC = 19, DEPTH_FUNC = 20, DEPTH_MASK = 21, COLOR_MASK = 22, CULL_FACE = 23, FRONT_FACE = 24, SHADE_MODEL = 25, ACTIVE_UNIT = 26, TEXTURE_BINDING = 27, MATRIX_MODE = 28,
|
||||
TEXTURE_MATRIX = 29, OFFSET_VALUES = 30, COLOR_MATERIAL_SETTINGS = 31, FRONT_AMBIENT = 32, FRONT_DIFFUSE = 33, FRONT_SPECULAR = 34, FRONT_EMISSION = 35, BACK_AMBIENT = 36, BACK_DIFFUSE = 37, BACK_SPECULAR = 38,
|
||||
BACK_EMISSION = 39, OVERLAY_COLOR = 40, CLIENT_ACTIVE_UNIT = 41;
|
||||
private static final int FIELD_COUNT = 42;
|
||||
private static final long IMPLICIT_INPUTS = bits(ACTIVE_UNIT, MATRIX_MODE);
|
||||
private static final long MATERIAL_BAKE_INPUTS = bits(COLOR, COLOR_MATERIAL_SETTINGS);
|
||||
private static final long DRAW_INPUTS = bits(CULL, TEXTURE0, TEXTURE1, COLOR, LIGHTMAP, OVERLAY_COLOR, CULL_FACE, FRONT_FACE, TEXTURE_BINDING);
|
||||
private static final long VERTEX_INPUTS = bits(NORMAL, TEXCOORD);
|
||||
private static final long MATERIAL_INPUTS = bits(BLEND, ALPHA, DEPTH, BLEND_FUNC, ALPHA_FUNC, DEPTH_FUNC, DEPTH_MASK, COLOR_MASK);
|
||||
private static final int[] CAPS = {GL11.GL_BLEND, GL11.GL_ALPHA_TEST, GL11.GL_DEPTH_TEST, GL11.GL_CULL_FACE, GL11.GL_LIGHTING, GL11.GL_NORMALIZE, GL12.GL_RESCALE_NORMAL, GL11.GL_LIGHT0, GL11.GL_LIGHT1, GL11.GL_TEXTURE_2D,
|
||||
GL11.GL_TEXTURE_2D, GL11.GL_POLYGON_OFFSET_FILL, GL11.GL_COLOR_MATERIAL};
|
||||
|
||||
private static final AtomicInteger openCaptures = new AtomicInteger();
|
||||
|
||||
private final GLContextState context;
|
||||
private final Matrix4f modelView = new Matrix4f();
|
||||
private final long[] attribWrites = new long[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
private final long[] matrixWrites = new long[GLStateManager.MAX_TEXTURE_STACK_DEPTH];
|
||||
private final boolean[] matrixInherited = new boolean[GLStateManager.MAX_TEXTURE_STACK_DEPTH];
|
||||
private final ExitState.Values current = new ExitState.Values();
|
||||
private final Reference2LongOpenHashMap<StateSet> restoredFieldsBySet = new Reference2LongOpenHashMap<>();
|
||||
private ExitState result;
|
||||
private int suspended, attribDepth, modelViewDepth, textureDepth, entryOverrides;
|
||||
private int filterTexture, filterMin, filterMag;
|
||||
private float filterAniso;
|
||||
private boolean filterOperation;
|
||||
private boolean textureInherited;
|
||||
|
||||
ExitStateCapture(GLContextState context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
static boolean anyOpen() {
|
||||
return openCaptures.get() != 0;
|
||||
}
|
||||
|
||||
private static boolean blendWritesReachVanilla() {
|
||||
final DeferredBlendHandler handler = GLSMHooks.blendHandler;
|
||||
return handler == null || !handler.isOverrideHeld() || handler.isBlendLocked();
|
||||
}
|
||||
|
||||
private static boolean alphaWritesReachVanilla() {
|
||||
final DeferredAlphaHandler handler = GLSMHooks.alphaHandler;
|
||||
return handler == null || !handler.isOverrideHeld() || handler.isAlphaTestLocked();
|
||||
}
|
||||
|
||||
private static boolean depthColorWritesReachVanilla() {
|
||||
final DeferredDepthColorHandler handler = GLSMHooks.depthColorHandler;
|
||||
return handler == null || !handler.isOverrideHeld() || handler.isDepthColorLocked();
|
||||
}
|
||||
|
||||
private static int overridesInControl() {
|
||||
return (blendWritesReachVanilla() ? 0 : 1) | (alphaWritesReachVanilla() ? 0 : 2) | (depthColorWritesReachVanilla() ? 0 : 4);
|
||||
}
|
||||
|
||||
private static boolean same(int field, ExitState.Values a, ExitState.Values b) {
|
||||
return switch (field) {
|
||||
case COLOR -> a.color.sameAs(b.color);
|
||||
case NORMAL -> a.normal.equals(b.normal);
|
||||
case TEXCOORD -> a.texCoord.equals(b.texCoord);
|
||||
case LIGHTMAP -> a.lightmapX == b.lightmapX && a.lightmapY == b.lightmapY;
|
||||
case OVERLAY_COLOR -> a.overlayColor.equals(b.overlayColor);
|
||||
case BLEND_FUNC -> a.blend.sameAs(b.blend);
|
||||
case ALPHA_FUNC -> a.alpha.sameAs(b.alpha);
|
||||
case DEPTH_FUNC -> a.depthFunction == b.depthFunction;
|
||||
case DEPTH_MASK -> a.depthMask == b.depthMask;
|
||||
case COLOR_MASK -> a.colorMask.sameAs(b.colorMask);
|
||||
case CULL_FACE -> a.cullFace == b.cullFace;
|
||||
case FRONT_FACE -> a.frontFace == b.frontFace;
|
||||
case ACTIVE_UNIT -> a.activeUnit == b.activeUnit;
|
||||
case TEXTURE_BINDING -> a.texture == b.texture;
|
||||
case MATRIX_MODE -> a.matrixMode == b.matrixMode;
|
||||
case TEXTURE_MATRIX -> a.textureMatrix.equals(b.textureMatrix);
|
||||
case COLOR_MATERIAL_SETTINGS -> a.materialFace == b.materialFace && a.materialParameter == b.materialParameter;
|
||||
default -> throw new IllegalArgumentException("Unsupported renderer state dependency " + field);
|
||||
};
|
||||
}
|
||||
|
||||
private static Vector4f vector(MaterialState state, int component) {
|
||||
return switch (component) {
|
||||
case 0 -> state.ambient;
|
||||
case 1 -> state.diffuse;
|
||||
case 2 -> state.specular;
|
||||
default -> state.emission;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean has(ExitState state, int field) {
|
||||
return has(state.writes, field);
|
||||
}
|
||||
|
||||
private static boolean has(long fields, int field) {
|
||||
return (fields & (1L << field)) != 0;
|
||||
}
|
||||
|
||||
private static long bits(int... fields) {
|
||||
long bits = 0;
|
||||
for (int field : fields) bits |= 1L << field;
|
||||
return bits;
|
||||
}
|
||||
|
||||
boolean active() {
|
||||
return result != null && result.valid && suspended == 0 && !context.poppingAttributes && !BatchStateGuard.isSuspended();
|
||||
}
|
||||
|
||||
void suspend() {
|
||||
suspended++;
|
||||
}
|
||||
|
||||
void resume() {
|
||||
if (suspended == 0) throw new IllegalStateException("Exit capture suspension underflow");
|
||||
suspended--;
|
||||
}
|
||||
|
||||
void begin(ExitState out) {
|
||||
out.clear();
|
||||
if (result != null) {
|
||||
result.valid = false;
|
||||
return;
|
||||
}
|
||||
result = out;
|
||||
openCaptures.incrementAndGet();
|
||||
filterTexture = 0;
|
||||
filterOperation = false;
|
||||
out.valid = suspended == 0 && !BatchStateGuard.isSuspended() && GLStateManager.isCachingEnabled() && !DisplayListManager.isRecording() && context.savedFilterTextureId == 0;
|
||||
if (!out.valid) return;
|
||||
out.dependencies = IMPLICIT_INPUTS;
|
||||
capture(out.entry, IMPLICIT_INPUTS | DRAW_INPUTS | MATERIAL_INPUTS | MATERIAL_BAKE_INPUTS | VERTEX_INPUTS | (1L << TEXTURE_MATRIX));
|
||||
textureInherited = true;
|
||||
modelView.set(context.modelViewMatrix);
|
||||
attribDepth = context.attribDepth;
|
||||
modelViewDepth = GLSMMatrices.getMatrixStackDepth(context.modelViewMatrix);
|
||||
textureDepth = GLSMMatrices.getMatrixStackDepth(context.textures.getTextureUnitMatrix(0));
|
||||
entryOverrides = overridesInControl();
|
||||
}
|
||||
|
||||
boolean finish(ExitState out) {
|
||||
if (result != out) {
|
||||
out.clear();
|
||||
return false;
|
||||
}
|
||||
if (textureInherited && has(out, TEXTURE_MATRIX)) out.dependencies |= 1L << TEXTURE_MATRIX;
|
||||
result = null;
|
||||
openCaptures.decrementAndGet();
|
||||
if (out.valid) out.valid = suspended == 0 && filterTexture == 0 && stacksMatchEntry() && overridesInControl() == entryOverrides;
|
||||
if (out.valid) {
|
||||
capture(out.value, out.writes);
|
||||
if ((out.writes & (15L << FRONT_AMBIENT)) != 0) out.frontMaterial.set(context.frontMaterial);
|
||||
if ((out.writes & (15L << BACK_AMBIENT)) != 0) out.backMaterial.set(context.backMaterial);
|
||||
out.textureDeleteCount = TextureInfoCache.INSTANCE.deleteCount();
|
||||
}
|
||||
filterTexture = 0;
|
||||
return out.valid;
|
||||
}
|
||||
|
||||
private boolean stacksMatchEntry() {
|
||||
return context.attribDepth == attribDepth && GLSMMatrices.getMatrixStackDepth(context.modelViewMatrix) == modelViewDepth
|
||||
&& GLSMMatrices.getMatrixStackDepth(context.textures.getTextureUnitMatrix(0)) == textureDepth && modelView.equals(context.modelViewMatrix);
|
||||
}
|
||||
|
||||
void cancel() {
|
||||
if (result != null) {
|
||||
result.clear();
|
||||
openCaptures.decrementAndGet();
|
||||
}
|
||||
result = null;
|
||||
filterTexture = 0;
|
||||
filterOperation = false;
|
||||
}
|
||||
|
||||
void reject() {
|
||||
if (active()) result.valid = false;
|
||||
}
|
||||
|
||||
// Callers record before their cache's unchanged-value early return
|
||||
void write(int field) {
|
||||
if (active()) record(field);
|
||||
}
|
||||
|
||||
void writeBlend() {
|
||||
if (active() && blendWritesReachVanilla()) record(ExitStateCapture.BLEND_FUNC);
|
||||
}
|
||||
|
||||
void writeAlpha() {
|
||||
if (active() && alphaWritesReachVanilla()) record(ExitStateCapture.ALPHA_FUNC);
|
||||
}
|
||||
|
||||
void writeDepthColor(int field) {
|
||||
if (active() && depthColorWritesReachVanilla()) record(field);
|
||||
}
|
||||
|
||||
private void record(int field) {
|
||||
result.writes |= 1L << field;
|
||||
}
|
||||
|
||||
void requireDrawState(boolean materialFromState) {
|
||||
if (!active()) return;
|
||||
long fields = (materialFromState ? DRAW_INPUTS | MATERIAL_INPUTS : DRAW_INPUTS) & ~(result.writes | result.dependencies);
|
||||
if ((fields & (1L << BLEND_FUNC)) != 0 && !context.blendMode.isEffectivelyEnabled()) fields &= ~(1L << BLEND_FUNC);
|
||||
if ((fields & (1L << ALPHA_FUNC)) != 0 && !context.alphaTest.isEffectivelyEnabled()) fields &= ~(1L << ALPHA_FUNC);
|
||||
result.dependencies |= fields;
|
||||
if (textureInherited) result.dependencies |= 1L << TEXTURE_MATRIX;
|
||||
}
|
||||
|
||||
void requireMaterialBakeInputs() {
|
||||
if (active()) result.dependencies |= MATERIAL_BAKE_INPUTS & ~result.writes;
|
||||
}
|
||||
|
||||
void requireVertexDefaults(boolean normal, boolean texCoord, boolean color, boolean lightmap) {
|
||||
if (!active()) return;
|
||||
final long fields = (normal ? 1L << NORMAL : 0) | (texCoord ? 1L << TEXCOORD : 0) | (color ? 1L << COLOR : 0) | (lightmap ? 1L << LIGHTMAP : 0);
|
||||
result.dependencies |= fields & ~result.writes;
|
||||
}
|
||||
|
||||
boolean beginTextureFilter(boolean nearest) {
|
||||
if (filterOperationBlocked()) return false;
|
||||
if (!nearest || filterTexture != 0 || context.savedFilterTextureId <= 0 || context.activeTextureUnit.getValue() != 0 || context.savedFilterMin < 0 || context.savedFilterMag < 0 || !(context.savedFilterAniso >= 1)) {
|
||||
reject();
|
||||
return false;
|
||||
}
|
||||
filterTexture = context.savedFilterTextureId;
|
||||
filterMin = context.savedFilterMin;
|
||||
filterMag = context.savedFilterMag;
|
||||
filterAniso = context.savedFilterAniso;
|
||||
startFilterOperation();
|
||||
return true;
|
||||
}
|
||||
|
||||
void finishTextureFilterSave() {
|
||||
endFilterOperation();
|
||||
if (active() && (savedFilterDiffers() || context.activeTextureUnit.getValue() != 0 || context.textures.getTextureUnitBindings(0).getBinding() != filterTexture || filterDiffersFrom(GL11.GL_NEAREST, GL11.GL_NEAREST, 1))) reject();
|
||||
}
|
||||
|
||||
boolean beginTextureFilterRestore() {
|
||||
if (filterOperationBlocked()) return false;
|
||||
if (savedFilterDiffers()) {
|
||||
reject();
|
||||
return false;
|
||||
}
|
||||
startFilterOperation();
|
||||
return true;
|
||||
}
|
||||
|
||||
void finishTextureFilterRestore() {
|
||||
endFilterOperation();
|
||||
if (active() && (savedFilterDiffers() || filterDiffersFrom(filterMin, filterMag, filterAniso))) reject();
|
||||
filterTexture = 0;
|
||||
}
|
||||
|
||||
private boolean filterOperationBlocked() {
|
||||
if (filterOperation) {
|
||||
failTextureFilter();
|
||||
return true;
|
||||
}
|
||||
return !active();
|
||||
}
|
||||
|
||||
private void startFilterOperation() {
|
||||
filterOperation = true;
|
||||
suspend();
|
||||
}
|
||||
|
||||
private void endFilterOperation() {
|
||||
resume();
|
||||
filterOperation = false;
|
||||
}
|
||||
|
||||
void failTextureFilter() {
|
||||
if (result != null) result.valid = false;
|
||||
}
|
||||
|
||||
void requireTextureFilter(int texture, boolean nearest) {
|
||||
if (filterTexture != 0 && texture == filterTexture && !nearest && active()) reject();
|
||||
}
|
||||
|
||||
private boolean savedFilterDiffers() {
|
||||
return filterTexture == 0 || context.savedFilterTextureId != filterTexture || context.savedFilterMin != filterMin || context.savedFilterMag != filterMag || context.savedFilterAniso != filterAniso;
|
||||
}
|
||||
|
||||
private boolean filterDiffersFrom(int min, int mag, float aniso) {
|
||||
final TextureInfo info = TextureInfoCache.INSTANCE.getInfo(filterTexture);
|
||||
return info == null || info.getMinFilter() != min || info.getMagFilter() != mag || info.getMaxAnisotropy() != aniso;
|
||||
}
|
||||
|
||||
boolean lightingWritten() {
|
||||
return active() && has(result, LIGHTING);
|
||||
}
|
||||
|
||||
int polygonOffsetWrites() {
|
||||
if (!active()) return 0;
|
||||
return (has(result, OFFSET) ? ExitState.POLYGON_OFFSET_ENABLE_WRITTEN : 0) | (has(result, OFFSET_VALUES) ? ExitState.POLYGON_OFFSET_VALUES_WRITTEN : 0);
|
||||
}
|
||||
|
||||
void capability(int cap, int unit) {
|
||||
if (!active()) return;
|
||||
int field = -1;
|
||||
for (int i = 0; i < CAPS.length; i++) {
|
||||
if (CAPS[i] == cap) {
|
||||
field = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (field == TEXTURE0) field = unit == 0 ? TEXTURE0 : unit == 1 ? TEXTURE1 : -1;
|
||||
if (field < 0) result.valid = false;
|
||||
else if (field == BLEND ? blendWritesReachVanilla() : field != ALPHA || alphaWritesReachVanilla()) record(field);
|
||||
}
|
||||
|
||||
void material(int face, int parameter) {
|
||||
if (!active()) return;
|
||||
int first = switch (parameter) {
|
||||
case GL11.GL_AMBIENT, GL11.GL_AMBIENT_AND_DIFFUSE -> 0;
|
||||
case GL11.GL_DIFFUSE -> 1;
|
||||
case GL11.GL_SPECULAR -> 2;
|
||||
case GL11.GL_EMISSION -> 3;
|
||||
default -> -1;
|
||||
};
|
||||
if (first < 0) {
|
||||
result.valid = false;
|
||||
return;
|
||||
}
|
||||
if (face != GL11.GL_BACK) {
|
||||
record(FRONT_AMBIENT + first);
|
||||
if (parameter == GL11.GL_AMBIENT_AND_DIFFUSE) record(FRONT_DIFFUSE);
|
||||
}
|
||||
if (face != GL11.GL_FRONT) {
|
||||
record(BACK_AMBIENT + first);
|
||||
if (parameter == GL11.GL_AMBIENT_AND_DIFFUSE) record(BACK_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
// Pushes and pops check result rather than active()
|
||||
void pushAttrib() {
|
||||
if (result == null) return;
|
||||
if (context.attribDepth < attribWrites.length) attribWrites[context.attribDepth] = result.writes;
|
||||
else result.valid = false;
|
||||
}
|
||||
|
||||
void popAttrib(StateSet set) {
|
||||
if (result == null) return;
|
||||
if (context.attribDepth <= attribDepth) {
|
||||
result.valid = false;
|
||||
return;
|
||||
}
|
||||
final long restored = restoredFields(set);
|
||||
result.writes = (result.writes & ~restored) | (attribWrites[context.attribDepth - 1] & restored);
|
||||
}
|
||||
|
||||
private long restoredFields(StateSet set) {
|
||||
long restored = restoredFieldsBySet.getOrDefault(set, -1L);
|
||||
if (restored >= 0) return restored;
|
||||
restored = 0;
|
||||
for (int field = 0; field < FIELD_COUNT; field++) {
|
||||
final CowStateStack<?> stack = stack(field);
|
||||
if (stack != null && set.contains(stack.stackId())) restored |= 1L << field;
|
||||
}
|
||||
restoredFieldsBySet.put(set, restored);
|
||||
return restored;
|
||||
}
|
||||
|
||||
private CowStateStack<?> stack(int field) {
|
||||
return switch (field) {
|
||||
case BLEND -> context.blendMode;
|
||||
case ALPHA -> context.alphaTest;
|
||||
case DEPTH -> context.depthTest;
|
||||
case CULL -> context.cullState;
|
||||
case LIGHTING -> context.lightingState;
|
||||
case NORMALIZE -> context.normalizeState;
|
||||
case RESCALE -> context.rescaleNormalState;
|
||||
case LIGHT0, LIGHT1 -> context.lightStates[field - LIGHT0];
|
||||
case TEXTURE0, TEXTURE1 -> context.textures.getTextureUnitStates(field - TEXTURE0);
|
||||
case OFFSET -> context.polygonOffsetFillState;
|
||||
case COLOR_MATERIAL -> context.colorMaterial;
|
||||
case COLOR -> context.color;
|
||||
case NORMAL -> context.ffp.normalStack;
|
||||
case TEXCOORD -> context.ffp.texCoordStack;
|
||||
case BLEND_FUNC -> context.blendState;
|
||||
case ALPHA_FUNC -> context.alphaState;
|
||||
case DEPTH_FUNC, DEPTH_MASK -> context.depthState;
|
||||
case COLOR_MASK -> context.colorMask;
|
||||
case CULL_FACE, FRONT_FACE, OFFSET_VALUES -> context.polygonState;
|
||||
case SHADE_MODEL -> context.shadeModelState;
|
||||
case ACTIVE_UNIT -> context.activeTextureUnit;
|
||||
case TEXTURE_BINDING -> context.textures.getTextureUnitBindings(0);
|
||||
case MATRIX_MODE -> context.matrixMode;
|
||||
// Face and parameter are restored together (GL_LIGHTING_BIT and the batch set hold both).
|
||||
case COLOR_MATERIAL_SETTINGS -> context.colorMaterialFace;
|
||||
case FRONT_AMBIENT, FRONT_DIFFUSE, FRONT_SPECULAR, FRONT_EMISSION -> context.frontMaterial;
|
||||
case BACK_AMBIENT, BACK_DIFFUSE, BACK_SPECULAR, BACK_EMISSION -> context.backMaterial;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
void matrixChange(boolean absolute) {
|
||||
if (result == null) return;
|
||||
final int mode = context.matrixMode.getMode();
|
||||
if ((absolute || mode != GL11.GL_MODELVIEW) && active()) recordMatrixChange(mode, context.activeTextureUnit.getValue(), absolute);
|
||||
}
|
||||
|
||||
void matrixChange(int mode, int unit, boolean absolute) {
|
||||
if (active()) recordMatrixChange(mode, unit, absolute);
|
||||
}
|
||||
|
||||
private void recordMatrixChange(int mode, int unit, boolean absolute) {
|
||||
if (mode == GL11.GL_MODELVIEW) {
|
||||
if (absolute) result.valid = false;
|
||||
return;
|
||||
}
|
||||
if (mode != GL11.GL_TEXTURE || unit != 0) {
|
||||
result.valid = false;
|
||||
return;
|
||||
}
|
||||
record(TEXTURE_MATRIX);
|
||||
if (absolute) textureInherited = false;
|
||||
}
|
||||
|
||||
void pushMatrix() {
|
||||
if (result == null) return;
|
||||
final int mode = context.matrixMode.getMode();
|
||||
if (mode == GL11.GL_TEXTURE && context.activeTextureUnit.getValue() == 0) {
|
||||
final int depth = GLSMMatrices.getMatrixStackDepth(context.textures.getTextureUnitMatrix(0));
|
||||
if (depth < matrixWrites.length) {
|
||||
matrixWrites[depth] = result.writes;
|
||||
matrixInherited[depth] = textureInherited;
|
||||
} else {
|
||||
result.valid = false;
|
||||
}
|
||||
} else if (mode != GL11.GL_MODELVIEW) {
|
||||
reject();
|
||||
}
|
||||
}
|
||||
|
||||
void popMatrix() {
|
||||
if (result == null) return;
|
||||
final int mode = context.matrixMode.getMode();
|
||||
final boolean texture = mode == GL11.GL_TEXTURE && context.activeTextureUnit.getValue() == 0;
|
||||
final Matrix4fStack matrix;
|
||||
final int entryDepth;
|
||||
if (mode == GL11.GL_MODELVIEW) {
|
||||
matrix = context.modelViewMatrix;
|
||||
entryDepth = modelViewDepth;
|
||||
} else if (texture) {
|
||||
matrix = context.textures.getTextureUnitMatrix(0);
|
||||
entryDepth = textureDepth;
|
||||
} else {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
final int depth = GLSMMatrices.getMatrixStackDepth(matrix);
|
||||
if (depth <= entryDepth) {
|
||||
result.valid = false;
|
||||
return;
|
||||
}
|
||||
if (texture) {
|
||||
final long bit = 1L << TEXTURE_MATRIX;
|
||||
result.writes = (result.writes & ~bit) | (matrixWrites[depth - 1] & bit);
|
||||
textureInherited = matrixInherited[depth - 1];
|
||||
}
|
||||
}
|
||||
|
||||
private void capture(ExitState.Values out, long fields) {
|
||||
out.enabled = 0;
|
||||
for (int field = 0; field < CAPS.length; field++) {
|
||||
if (has(fields, field) && ((BooleanStateStack) Objects.requireNonNull(stack(field))).isEffectivelyEnabled()) out.enabled |= 1L << field;
|
||||
}
|
||||
if (has(fields, COLOR)) out.color.set(context.color);
|
||||
if (has(fields, NORMAL)) out.normal.set(context.ffp.currentNormal);
|
||||
if (has(fields, TEXCOORD)) out.texCoord.set(context.ffp.currentTexCoords[0]);
|
||||
if (has(fields, LIGHTMAP)) {
|
||||
out.lightmapX = context.lastBrightnessX;
|
||||
out.lightmapY = context.lastBrightnessY;
|
||||
}
|
||||
if (has(fields, SHADER_COLOR)) out.shaderColor.set(context.shaderColorR, context.shaderColorG, context.shaderColorB, context.shaderColorA);
|
||||
if (has(fields, OVERLAY_COLOR)) out.overlayColor.set(context.overlayR, context.overlayG, context.overlayB, context.overlayA);
|
||||
if (has(fields, BLEND_FUNC)) context.blendState.readEffective(out.blend);
|
||||
if (has(fields, ALPHA_FUNC)) context.alphaState.readEffective(out.alpha);
|
||||
if (has(fields, COLOR_MASK)) context.colorMask.readEffective(out.colorMask);
|
||||
if (has(fields, DEPTH_FUNC)) out.depthFunction = context.depthState.getFunc();
|
||||
if (has(fields, DEPTH_MASK)) out.depthMask = context.depthState.isEffectiveMaskEnabled();
|
||||
if (has(fields, CULL_FACE)) out.cullFace = context.polygonState.getCullFaceMode();
|
||||
if (has(fields, FRONT_FACE)) out.frontFace = context.polygonState.getFrontFace();
|
||||
if (has(fields, OFFSET_VALUES)) {
|
||||
out.offsetFactor = context.polygonState.getOffsetFactor();
|
||||
out.offsetUnits = context.polygonState.getOffsetUnits();
|
||||
out.offsetClamp = context.polygonState.getOffsetClamp();
|
||||
}
|
||||
if (has(fields, SHADE_MODEL)) out.shadeModel = context.shadeModelState.getValue();
|
||||
if (has(fields, ACTIVE_UNIT)) out.activeUnit = context.activeTextureUnit.getValue();
|
||||
if (has(fields, CLIENT_ACTIVE_UNIT)) out.clientActiveUnit = context.clientActiveTextureUnit;
|
||||
if (has(fields, MATRIX_MODE)) out.matrixMode = context.matrixMode.getMode();
|
||||
if (has(fields, TEXTURE_BINDING)) out.texture = context.textures.getTextureUnitBindings(0).getBinding();
|
||||
if (has(fields, TEXTURE_MATRIX)) out.textureMatrix.set(context.textures.getTextureUnitMatrix(0));
|
||||
if (has(fields, COLOR_MATERIAL_SETTINGS)) {
|
||||
out.materialFace = context.colorMaterialFace.getValue();
|
||||
out.materialParameter = context.colorMaterialParameter.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
boolean canApply(ExitState in) {
|
||||
if (!in.valid || result != null || !GLStateManager.isCachingEnabled() || DisplayListManager.isRecording() || context.savedFilterTextureId != 0) return false;
|
||||
if (in.textureDeleteCount != TextureInfoCache.INSTANCE.deleteCount()) return false;
|
||||
capture(current, in.dependencies);
|
||||
if (((current.enabled ^ in.entry.enabled) & in.dependencies & ((1L << CAPS.length) - 1)) != 0) return false;
|
||||
long remaining = in.dependencies & -(1L << CAPS.length);
|
||||
while (remaining != 0) {
|
||||
final int field = Long.numberOfTrailingZeros(remaining);
|
||||
if (!same(field, in.entry, current)) return false;
|
||||
remaining &= remaining - 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void apply(ExitState state) {
|
||||
if (!state.valid) throw new IllegalStateException("Invalid renderer exit state");
|
||||
if (result != null) throw new IllegalStateException("Exit state applied while a capture is open");
|
||||
final ExitState.Values in = state.value;
|
||||
final long fields = state.writes;
|
||||
final int liveUnit = context.activeTextureUnit.getValue();
|
||||
// Capabilities go first so the glColor4f below bakes into the material only if color material is on at exit.
|
||||
for (int field = 0; field < CAPS.length; field++) {
|
||||
if (!has(fields, field)) continue;
|
||||
if (field == TEXTURE0 || field == TEXTURE1) GLSMTextures.glActiveTexture(GL13.GL_TEXTURE0 + field - TEXTURE0);
|
||||
// glEnable would bake the live color, not the exit color, into the material.
|
||||
if (field == COLOR_MATERIAL) {
|
||||
context.colorMaterial.setEnabled((in.enabled & (1L << field)) != 0);
|
||||
} else if ((in.enabled & (1L << field)) != 0) GLSMEnable.glEnable(CAPS[field]);
|
||||
else GLSMEnable.glDisable(CAPS[field]);
|
||||
}
|
||||
if (has(fields, COLOR)) GLSMCurrentAttribs.glColor4f(in.color.getRed(), in.color.getGreen(), in.color.getBlue(), in.color.getAlpha());
|
||||
if (has(fields, NORMAL)) GLSMCurrentAttribs.glNormal3f(in.normal.x, in.normal.y, in.normal.z);
|
||||
if (has(fields, TEXCOORD)) GLSMCurrentAttribs.glTexCoord4f(in.texCoord.x, in.texCoord.y, in.texCoord.z, in.texCoord.w);
|
||||
if (has(fields, LIGHTMAP)) GLSMCurrentAttribs.setLightmapTextureCoords(GL13.GL_TEXTURE1, in.lightmapX, in.lightmapY);
|
||||
if (has(fields, SHADER_COLOR)) GLSMCurrentAttribs.setShaderColor(in.shaderColor.x, in.shaderColor.y, in.shaderColor.z, in.shaderColor.w);
|
||||
if (has(fields, OVERLAY_COLOR)) GLSMCurrentAttribs.setOverlayColor(in.overlayColor.x, in.overlayColor.y, in.overlayColor.z, in.overlayColor.w);
|
||||
if (has(fields, BLEND_FUNC)) GLSMBlend.tryBlendFuncSeparate(in.blend.getSrcRgb(), in.blend.getDstRgb(), in.blend.getSrcAlpha(), in.blend.getDstAlpha());
|
||||
if (has(fields, ALPHA_FUNC)) GLSMDepthStencilAlpha.glAlphaFunc(in.alpha.getFunction(), in.alpha.getReference());
|
||||
if (has(fields, DEPTH_FUNC)) GLSMDepthStencilAlpha.glDepthFunc(in.depthFunction);
|
||||
if (has(fields, DEPTH_MASK)) GLSMDepthStencilAlpha.glDepthMask(in.depthMask);
|
||||
if (has(fields, COLOR_MASK)) GLSMBlend.glColorMask(in.colorMask.red, in.colorMask.green, in.colorMask.blue, in.colorMask.alpha);
|
||||
if (has(fields, CULL_FACE)) GLSMRasterizer.glCullFace(in.cullFace);
|
||||
if (has(fields, FRONT_FACE)) GLSMRasterizer.glFrontFace(in.frontFace);
|
||||
if (has(fields, SHADE_MODEL)) GLSMRasterizer.glShadeModel(in.shadeModel);
|
||||
if (has(fields, OFFSET_VALUES)) GLSMRasterizer.glPolygonOffsetClamp(in.offsetFactor, in.offsetUnits, in.offsetClamp);
|
||||
if (has(fields, TEXTURE_BINDING)) {
|
||||
GLSMTextures.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLSMTextures.glBindTexture(GL11.GL_TEXTURE_2D, in.texture);
|
||||
}
|
||||
if (has(fields, TEXTURE_MATRIX)) GLSMMatrices.setTextureMatrix(0, in.textureMatrix);
|
||||
if (has(fields, COLOR_MATERIAL_SETTINGS)) GLSMLighting.glColorMaterial(in.materialFace, in.materialParameter);
|
||||
boolean materialChanged = false;
|
||||
for (int field = FRONT_AMBIENT; field <= BACK_EMISSION; field++) {
|
||||
if (!has(fields, field)) continue;
|
||||
final boolean front = field < BACK_AMBIENT;
|
||||
final int component = (field - FRONT_AMBIENT) & 3;
|
||||
final Vector4f source = vector(front ? state.frontMaterial : state.backMaterial, component);
|
||||
final var target = front ? context.frontMaterial : context.backMaterial;
|
||||
if (vector(target, component).equals(source)) continue;
|
||||
target.beforeModify();
|
||||
vector(target, component).set(source);
|
||||
materialChanged = true;
|
||||
}
|
||||
if (materialChanged) context.lightingGeneration++;
|
||||
GLSMTextures.glActiveTexture(GL13.GL_TEXTURE0 + (has(fields, ACTIVE_UNIT) ? in.activeUnit : liveUnit));
|
||||
if (has(fields, CLIENT_ACTIVE_UNIT)) GLSMTextures.glClientActiveTexture(GL13.GL_TEXTURE0 + in.clientActiveUnit);
|
||||
if (has(fields, MATRIX_MODE)) GLSMMatrices.glMatrixMode(in.matrixMode);
|
||||
}
|
||||
}
|
||||
@@ -68,10 +68,10 @@ public class Feature {
|
||||
*/
|
||||
private static void addTextureGenStates(Set<IStateStack<?>> collection) {
|
||||
for(int i = 0 ; i < GLStateManager.MAX_TEXTURE_UNITS; i++) {
|
||||
collection.add(GLStateManager.getTextures().getTexGenSStates(i));
|
||||
collection.add(GLStateManager.getTextures().getTexGenTStates(i));
|
||||
collection.add(GLStateManager.getTextures().getTexGenRStates(i));
|
||||
collection.add(GLStateManager.getTextures().getTexGenQStates(i));
|
||||
collection.add(GLSMTextures.getTextures().getTexGenSStates(i));
|
||||
collection.add(GLSMTextures.getTextures().getTexGenTStates(i));
|
||||
collection.add(GLSMTextures.getTextures().getTexGenRStates(i));
|
||||
collection.add(GLSMTextures.getTextures().getTexGenQStates(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,24 +79,24 @@ public class Feature {
|
||||
final Int2ObjectMap<Set<IStateStack<?>>> attribToFeatures = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
attribToFeatures.put(GL11.GL_COLOR_BUFFER_BIT, ImmutableSet.of(
|
||||
GLStateManager.getAlphaTest()
|
||||
, GLStateManager.getAlphaState()
|
||||
, GLStateManager.getBlendMode()
|
||||
, GLStateManager.getBlendState()
|
||||
, GLStateManager.getColorLogicOpState()
|
||||
, GLStateManager.getDitherState()
|
||||
, GLStateManager.getDrawBuffer()
|
||||
, GLStateManager.getIndexLogicOpState()
|
||||
, GLStateManager.getLogicOpMode()
|
||||
, GLStateManager.getColorMask()
|
||||
, GLStateManager.getClearColor()
|
||||
GLSMDepthStencilAlpha.getAlphaTest()
|
||||
, GLSMDepthStencilAlpha.getAlphaState()
|
||||
, GLSMBlend.getBlendMode()
|
||||
, GLSMBlend.getBlendState()
|
||||
, GLSMBlend.getColorLogicOpState()
|
||||
, GLSMRasterizer.getDitherState()
|
||||
, GLSMFramebuffer.getDrawBuffer()
|
||||
, GLSMBlend.getIndexLogicOpState()
|
||||
, GLSMBlend.getLogicOpMode()
|
||||
, GLSMBlend.getColorMask()
|
||||
, GLSMBlend.getClearColor()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_CURRENT_BIT, ImmutableSet.of(
|
||||
GLStateManager.getColor()
|
||||
, GLStateManager.getSecondaryColor() // Current secondary color
|
||||
GLSMCurrentAttribs.getColor()
|
||||
, GLSMCurrentAttribs.getSecondaryColor() // Current secondary color
|
||||
, ShaderManager.getNormalStack() // Current normal vector
|
||||
, ShaderManager.getTexCoordStack() // Current texture coordinates
|
||||
, GLStateManager.getEdgeFlagState()
|
||||
, GLSMRasterizer.getEdgeFlagState()
|
||||
// Current color index
|
||||
// Current raster position
|
||||
// GL_CURRENT_RASTER_POSITION_VALID flag
|
||||
@@ -106,82 +106,82 @@ public class Feature {
|
||||
// GL_EDGE_FLAG flag
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_DEPTH_BUFFER_BIT, ImmutableSet.of(
|
||||
GLStateManager.getDepthTest()
|
||||
, GLStateManager.getDepthState()
|
||||
GLSMDepthStencilAlpha.getDepthTest()
|
||||
, GLSMDepthStencilAlpha.getDepthState()
|
||||
// Depth buffer clear value
|
||||
// GL_DEPTH_WRITEMASK enable bit
|
||||
));
|
||||
|
||||
final HashSet<IStateStack<?>> enableBits = new HashSet<>(ImmutableSet.of(
|
||||
GLStateManager.getAlphaTest()
|
||||
, GLStateManager.getAutoNormalState()
|
||||
, GLStateManager.getBlendMode()
|
||||
, GLStateManager.getColorLogicOpState()
|
||||
, GLStateManager.getColorMaterial()
|
||||
, GLStateManager.getColorSumState()
|
||||
, GLStateManager.getCullState()
|
||||
, GLStateManager.getDepthTest()
|
||||
, GLStateManager.getDitherState()
|
||||
, GLStateManager.getFogMode()
|
||||
, GLStateManager.getIndexLogicOpState()
|
||||
, GLStateManager.getLightStates()[0] // GL_LIGHT0
|
||||
, GLStateManager.getLightStates()[1] // GL_LIGHT1
|
||||
, GLStateManager.getLightStates()[2] // GL_LIGHT2
|
||||
, GLStateManager.getLightStates()[3] // GL_LIGHT3
|
||||
, GLStateManager.getLightStates()[4] // GL_LIGHT4
|
||||
, GLStateManager.getLightStates()[5] // GL_LIGHT5
|
||||
, GLStateManager.getLightStates()[6] // GL_LIGHT6
|
||||
, GLStateManager.getLightStates()[7] // GL_LIGHT7
|
||||
, GLStateManager.getLightingState()
|
||||
, GLStateManager.getLineSmoothState()
|
||||
, GLStateManager.getLineStippleState()
|
||||
, GLStateManager.getMap1Color4State()
|
||||
, GLStateManager.getMap1IndexState()
|
||||
, GLStateManager.getMap1NormalState()
|
||||
, GLStateManager.getMap1TextureCoord1State()
|
||||
, GLStateManager.getMap1TextureCoord2State()
|
||||
, GLStateManager.getMap1TextureCoord3State()
|
||||
, GLStateManager.getMap1TextureCoord4State()
|
||||
, GLStateManager.getMap1Vertex3State()
|
||||
, GLStateManager.getMap1Vertex4State()
|
||||
, GLStateManager.getMap2Color4State()
|
||||
, GLStateManager.getMap2IndexState()
|
||||
, GLStateManager.getMap2NormalState()
|
||||
, GLStateManager.getMap2TextureCoord1State()
|
||||
, GLStateManager.getMap2TextureCoord2State()
|
||||
, GLStateManager.getMap2TextureCoord3State()
|
||||
, GLStateManager.getMap2TextureCoord4State()
|
||||
, GLStateManager.getMap2Vertex3State()
|
||||
, GLStateManager.getMap2Vertex4State()
|
||||
, GLStateManager.getMultisampleState()
|
||||
, GLStateManager.getNormalizeState()
|
||||
, GLStateManager.getPointSmoothState()
|
||||
, GLStateManager.getPolygonOffsetPointState()
|
||||
, GLStateManager.getPolygonOffsetLineState()
|
||||
, GLStateManager.getPolygonOffsetFillState()
|
||||
, GLStateManager.getPointSpriteState()
|
||||
, GLStateManager.getVertexProgramTwoSideState()
|
||||
, GLStateManager.getPolygonSmoothState()
|
||||
, GLStateManager.getPolygonStippleState()
|
||||
, GLStateManager.getRescaleNormalState()
|
||||
, GLStateManager.getSampleAlphaToCoverageState()
|
||||
, GLStateManager.getSampleAlphaToOneState()
|
||||
, GLStateManager.getSampleCoverageState()
|
||||
, GLStateManager.getScissorTest()
|
||||
, GLStateManager.getStencilTest()
|
||||
GLSMDepthStencilAlpha.getAlphaTest()
|
||||
, GLSMRasterizer.getAutoNormalState()
|
||||
, GLSMBlend.getBlendMode()
|
||||
, GLSMBlend.getColorLogicOpState()
|
||||
, GLSMLighting.getColorMaterial()
|
||||
, GLSMCurrentAttribs.getColorSumState()
|
||||
, GLSMRasterizer.getCullState()
|
||||
, GLSMDepthStencilAlpha.getDepthTest()
|
||||
, GLSMRasterizer.getDitherState()
|
||||
, GLSMFog.getFogMode()
|
||||
, GLSMBlend.getIndexLogicOpState()
|
||||
, GLSMLighting.getLightStates()[0] // GL_LIGHT0
|
||||
, GLSMLighting.getLightStates()[1] // GL_LIGHT1
|
||||
, GLSMLighting.getLightStates()[2] // GL_LIGHT2
|
||||
, GLSMLighting.getLightStates()[3] // GL_LIGHT3
|
||||
, GLSMLighting.getLightStates()[4] // GL_LIGHT4
|
||||
, GLSMLighting.getLightStates()[5] // GL_LIGHT5
|
||||
, GLSMLighting.getLightStates()[6] // GL_LIGHT6
|
||||
, GLSMLighting.getLightStates()[7] // GL_LIGHT7
|
||||
, GLSMLighting.getLightingState()
|
||||
, GLSMRasterizer.getLineSmoothState()
|
||||
, GLSMRasterizer.getLineStippleState()
|
||||
, GLSMRasterizer.getMap1Color4State()
|
||||
, GLSMRasterizer.getMap1IndexState()
|
||||
, GLSMRasterizer.getMap1NormalState()
|
||||
, GLSMRasterizer.getMap1TextureCoord1State()
|
||||
, GLSMRasterizer.getMap1TextureCoord2State()
|
||||
, GLSMRasterizer.getMap1TextureCoord3State()
|
||||
, GLSMRasterizer.getMap1TextureCoord4State()
|
||||
, GLSMRasterizer.getMap1Vertex3State()
|
||||
, GLSMRasterizer.getMap1Vertex4State()
|
||||
, GLSMRasterizer.getMap2Color4State()
|
||||
, GLSMRasterizer.getMap2IndexState()
|
||||
, GLSMRasterizer.getMap2NormalState()
|
||||
, GLSMRasterizer.getMap2TextureCoord1State()
|
||||
, GLSMRasterizer.getMap2TextureCoord2State()
|
||||
, GLSMRasterizer.getMap2TextureCoord3State()
|
||||
, GLSMRasterizer.getMap2TextureCoord4State()
|
||||
, GLSMRasterizer.getMap2Vertex3State()
|
||||
, GLSMRasterizer.getMap2Vertex4State()
|
||||
, GLSMRasterizer.getMultisampleState()
|
||||
, GLSMLighting.getNormalizeState()
|
||||
, GLSMRasterizer.getPointSmoothState()
|
||||
, GLSMRasterizer.getPolygonOffsetPointState()
|
||||
, GLSMRasterizer.getPolygonOffsetLineState()
|
||||
, GLSMRasterizer.getPolygonOffsetFillState()
|
||||
, GLSMRasterizer.getPointSpriteState()
|
||||
, GLSMPrograms.getVertexProgramTwoSideState()
|
||||
, GLSMRasterizer.getPolygonSmoothState()
|
||||
, GLSMRasterizer.getPolygonStippleState()
|
||||
, GLSMLighting.getRescaleNormalState()
|
||||
, GLSMRasterizer.getSampleAlphaToCoverageState()
|
||||
, GLSMRasterizer.getSampleAlphaToOneState()
|
||||
, GLSMRasterizer.getSampleCoverageState()
|
||||
, GLSMRasterizer.getScissorTest()
|
||||
, GLSMDepthStencilAlpha.getStencilTest()
|
||||
));
|
||||
|
||||
// Enable bits for the user-definable clipping planes
|
||||
for(int i = 0; i < GLStateManager.getClipPlaneStates().length; i++) {
|
||||
enableBits.add(GLStateManager.getClipPlaneStates()[i]);
|
||||
for(int i = 0; i < GLSMRasterizer.getClipPlaneStates().length; i++) {
|
||||
enableBits.add(GLSMRasterizer.getClipPlaneStates()[i]);
|
||||
}
|
||||
|
||||
// GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D flags
|
||||
for(int i = 0 ; i < GLStateManager.MAX_TEXTURE_UNITS; i++) {
|
||||
enableBits.add(GLStateManager.getTextures().getTexture1DStates(i));
|
||||
enableBits.add(GLStateManager.getTextures().getTextureUnitStates(i));
|
||||
enableBits.add(GLStateManager.getTextures().getTexture3DStates(i));
|
||||
enableBits.add(GLStateManager.getTextures().getTextureCubeMapStates(i));
|
||||
enableBits.add(GLSMTextures.getTextures().getTexture1DStates(i));
|
||||
enableBits.add(GLSMTextures.getTextures().getTextureUnitStates(i));
|
||||
enableBits.add(GLSMTextures.getTextures().getTexture3DStates(i));
|
||||
enableBits.add(GLSMTextures.getTextures().getTextureCubeMapStates(i));
|
||||
}
|
||||
|
||||
// Flags GL_TEXTURE_GEN_x where x is S, T, R, or Q
|
||||
@@ -189,30 +189,30 @@ public class Feature {
|
||||
|
||||
attribToFeatures.put(GL11.GL_ENABLE_BIT, enableBits);
|
||||
attribToFeatures.put(GL11.GL_EVAL_BIT, ImmutableSet.of(
|
||||
GLStateManager.getAutoNormalState()
|
||||
, GLStateManager.getMap1Color4State()
|
||||
, GLStateManager.getMap1IndexState()
|
||||
, GLStateManager.getMap1NormalState()
|
||||
, GLStateManager.getMap1TextureCoord1State()
|
||||
, GLStateManager.getMap1TextureCoord2State()
|
||||
, GLStateManager.getMap1TextureCoord3State()
|
||||
, GLStateManager.getMap1TextureCoord4State()
|
||||
, GLStateManager.getMap1Vertex3State()
|
||||
, GLStateManager.getMap1Vertex4State()
|
||||
, GLStateManager.getMap2Color4State()
|
||||
, GLStateManager.getMap2IndexState()
|
||||
, GLStateManager.getMap2NormalState()
|
||||
, GLStateManager.getMap2TextureCoord1State()
|
||||
, GLStateManager.getMap2TextureCoord2State()
|
||||
, GLStateManager.getMap2TextureCoord3State()
|
||||
, GLStateManager.getMap2TextureCoord4State()
|
||||
, GLStateManager.getMap2Vertex3State()
|
||||
, GLStateManager.getMap2Vertex4State()
|
||||
GLSMRasterizer.getAutoNormalState()
|
||||
, GLSMRasterizer.getMap1Color4State()
|
||||
, GLSMRasterizer.getMap1IndexState()
|
||||
, GLSMRasterizer.getMap1NormalState()
|
||||
, GLSMRasterizer.getMap1TextureCoord1State()
|
||||
, GLSMRasterizer.getMap1TextureCoord2State()
|
||||
, GLSMRasterizer.getMap1TextureCoord3State()
|
||||
, GLSMRasterizer.getMap1TextureCoord4State()
|
||||
, GLSMRasterizer.getMap1Vertex3State()
|
||||
, GLSMRasterizer.getMap1Vertex4State()
|
||||
, GLSMRasterizer.getMap2Color4State()
|
||||
, GLSMRasterizer.getMap2IndexState()
|
||||
, GLSMRasterizer.getMap2NormalState()
|
||||
, GLSMRasterizer.getMap2TextureCoord1State()
|
||||
, GLSMRasterizer.getMap2TextureCoord2State()
|
||||
, GLSMRasterizer.getMap2TextureCoord3State()
|
||||
, GLSMRasterizer.getMap2TextureCoord4State()
|
||||
, GLSMRasterizer.getMap2Vertex3State()
|
||||
, GLSMRasterizer.getMap2Vertex4State()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_FOG_BIT, ImmutableSet.of(
|
||||
GLStateManager.getFogMode()
|
||||
, GLStateManager.getColorSumState()
|
||||
, GLStateManager.getFogState()
|
||||
GLSMFog.getFogMode()
|
||||
, GLSMCurrentAttribs.getColorSumState()
|
||||
, GLSMFog.getFogState()
|
||||
// ^^ Fog density
|
||||
// ^^ Linear fog start
|
||||
// ^^ Linear fog end
|
||||
@@ -220,54 +220,54 @@ public class Feature {
|
||||
// ^^ GL_FOG_MODE value
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_HINT_BIT, ImmutableSet.of(
|
||||
GLStateManager.getHintState()
|
||||
GLSMRasterizer.getHintState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_LIGHTING_BIT, ImmutableSet.of(
|
||||
GLStateManager.getColorMaterial()
|
||||
, GLStateManager.getColorMaterialFace()
|
||||
, GLStateManager.getColorMaterialParameter()
|
||||
, GLStateManager.getLightModel()
|
||||
, GLStateManager.getLightingState()
|
||||
GLSMLighting.getColorMaterial()
|
||||
, GLSMLighting.getColorMaterialFace()
|
||||
, GLSMLighting.getColorMaterialParameter()
|
||||
, GLSMLighting.getLightModel()
|
||||
, GLSMLighting.getLightingState()
|
||||
// Enable bit for each light
|
||||
, GLStateManager.getLightStates()[0] // GL_LIGHT0
|
||||
, GLStateManager.getLightStates()[1] // GL_LIGHT1
|
||||
, GLStateManager.getLightStates()[2] // GL_LIGHT2
|
||||
, GLStateManager.getLightStates()[3] // GL_LIGHT3
|
||||
, GLStateManager.getLightStates()[4] // GL_LIGHT4
|
||||
, GLStateManager.getLightStates()[5] // GL_LIGHT5
|
||||
, GLStateManager.getLightStates()[6] // GL_LIGHT6
|
||||
, GLStateManager.getLightStates()[7] // GL_LIGHT7
|
||||
, GLSMLighting.getLightStates()[0] // GL_LIGHT0
|
||||
, GLSMLighting.getLightStates()[1] // GL_LIGHT1
|
||||
, GLSMLighting.getLightStates()[2] // GL_LIGHT2
|
||||
, GLSMLighting.getLightStates()[3] // GL_LIGHT3
|
||||
, GLSMLighting.getLightStates()[4] // GL_LIGHT4
|
||||
, GLSMLighting.getLightStates()[5] // GL_LIGHT5
|
||||
, GLSMLighting.getLightStates()[6] // GL_LIGHT6
|
||||
, GLSMLighting.getLightStates()[7] // GL_LIGHT7
|
||||
// Ambient, diffuse, and specular intensity for each light
|
||||
// Direction, position, exponent, and cutoff angle for each light
|
||||
// Constant, linear, and quadratic attenuation factors for each light
|
||||
, GLStateManager.getLightDataStates()[0]
|
||||
, GLStateManager.getLightDataStates()[1]
|
||||
, GLStateManager.getLightDataStates()[2]
|
||||
, GLStateManager.getLightDataStates()[3]
|
||||
, GLStateManager.getLightDataStates()[4]
|
||||
, GLStateManager.getLightDataStates()[5]
|
||||
, GLStateManager.getLightDataStates()[6]
|
||||
, GLStateManager.getLightDataStates()[7]
|
||||
, GLSMLighting.getLightDataStates()[0]
|
||||
, GLSMLighting.getLightDataStates()[1]
|
||||
, GLSMLighting.getLightDataStates()[2]
|
||||
, GLSMLighting.getLightDataStates()[3]
|
||||
, GLSMLighting.getLightDataStates()[4]
|
||||
, GLSMLighting.getLightDataStates()[5]
|
||||
, GLSMLighting.getLightDataStates()[6]
|
||||
, GLSMLighting.getLightDataStates()[7]
|
||||
// Ambient, diffuse, specular, and emissive color for each material
|
||||
// Ambient, diffuse, and specular color indices for each material
|
||||
// Specular exponent for each material
|
||||
, GLStateManager.getFrontMaterial()
|
||||
, GLStateManager.getBackMaterial()
|
||||
, GLStateManager.getShadeModelState()
|
||||
, GLSMLighting.getFrontMaterial()
|
||||
, GLSMLighting.getBackMaterial()
|
||||
, GLSMRasterizer.getShadeModelState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_LINE_BIT, ImmutableSet.of(
|
||||
GLStateManager.getLineSmoothState()
|
||||
, GLStateManager.getLineStippleState()
|
||||
, GLStateManager.getLineState()
|
||||
GLSMRasterizer.getLineSmoothState()
|
||||
, GLSMRasterizer.getLineStippleState()
|
||||
, GLSMRasterizer.getLineState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_LIST_BIT, ImmutableSet.of(
|
||||
// GL_LIST_BASE setting
|
||||
));
|
||||
attribToFeatures.put(GL13.GL_MULTISAMPLE_BIT, ImmutableSet.of(
|
||||
GLStateManager.getMultisampleState()
|
||||
, GLStateManager.getSampleAlphaToCoverageState()
|
||||
, GLStateManager.getSampleAlphaToOneState()
|
||||
, GLStateManager.getSampleCoverageState()
|
||||
GLSMRasterizer.getMultisampleState()
|
||||
, GLSMRasterizer.getSampleAlphaToCoverageState()
|
||||
, GLSMRasterizer.getSampleAlphaToOneState()
|
||||
, GLSMRasterizer.getSampleCoverageState()
|
||||
// GL_SAMPLE_COVERAGE_VALUE value
|
||||
// GL_SAMPLE_COVERAGE_INVERT value
|
||||
));
|
||||
@@ -283,32 +283,32 @@ public class Feature {
|
||||
// GL_READ_BUFFER setting
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_POINT_BIT, ImmutableSet.of(
|
||||
GLStateManager.getPointSmoothState()
|
||||
, GLStateManager.getPointSpriteState()
|
||||
, GLStateManager.getPointState()
|
||||
GLSMRasterizer.getPointSmoothState()
|
||||
, GLSMRasterizer.getPointSpriteState()
|
||||
, GLSMRasterizer.getPointState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_POLYGON_BIT, ImmutableSet.of(
|
||||
GLStateManager.getCullState()
|
||||
, GLStateManager.getPolygonSmoothState()
|
||||
, GLStateManager.getPolygonStippleState()
|
||||
, GLStateManager.getPolygonOffsetFillState()
|
||||
, GLStateManager.getPolygonOffsetLineState()
|
||||
, GLStateManager.getPolygonOffsetPointState()
|
||||
, GLStateManager.getPolygonState()
|
||||
GLSMRasterizer.getCullState()
|
||||
, GLSMRasterizer.getPolygonSmoothState()
|
||||
, GLSMRasterizer.getPolygonStippleState()
|
||||
, GLSMRasterizer.getPolygonOffsetFillState()
|
||||
, GLSMRasterizer.getPolygonOffsetLineState()
|
||||
, GLSMRasterizer.getPolygonOffsetPointState()
|
||||
, GLSMRasterizer.getPolygonState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_POLYGON_STIPPLE_BIT, ImmutableSet.of(
|
||||
// Polygon stipple pattern
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_SCISSOR_BIT, ImmutableSet.of(
|
||||
GLStateManager.getScissorTest()
|
||||
, GLStateManager.getScissorState()
|
||||
GLSMRasterizer.getScissorTest()
|
||||
, GLSMRasterizer.getScissorState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_STENCIL_BUFFER_BIT, ImmutableSet.of(
|
||||
GLStateManager.getStencilTest()
|
||||
, GLStateManager.getStencilState()
|
||||
GLSMDepthStencilAlpha.getStencilTest()
|
||||
, GLSMDepthStencilAlpha.getStencilState()
|
||||
));
|
||||
final Set<IStateStack<?>> textureAttribs = new HashSet<>(ImmutableSet.of(
|
||||
GLStateManager.getActiveTextureUnitStack()
|
||||
GLSMTextures.getActiveTextureUnitStack()
|
||||
// GL_TEXTURE_ENV_MODE + GL_TEXTURE_ENV_COLOR — now per-unit in TexEnvState (added below)
|
||||
// Enable bits for the four texture coordinates
|
||||
|
||||
@@ -325,12 +325,12 @@ public class Feature {
|
||||
|
||||
// Current Texture Bindings - GL_TEXTURE_BINDING_2D + per-unit TexEnvState
|
||||
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));
|
||||
textureAttribs.add(GLSMTextures.getTextures().getTextureUnitBindings(i));
|
||||
textureAttribs.add(GLSMTextures.getTextures().getTexEnvState(i));
|
||||
textureAttribs.add(GLSMTextures.getTextures().getTexture1DStates(i));
|
||||
textureAttribs.add(GLSMTextures.getTextures().getTextureUnitStates(i));
|
||||
textureAttribs.add(GLSMTextures.getTextures().getTexture3DStates(i));
|
||||
textureAttribs.add(GLSMTextures.getTextures().getTextureCubeMapStates(i));
|
||||
}
|
||||
|
||||
// Enable bits GL_TEXTURE_GEN_x where x is S, T, R, or Q
|
||||
@@ -341,17 +341,17 @@ public class Feature {
|
||||
final Set<IStateStack<?>> transformAttribs = new HashSet<>(ImmutableSet.of(
|
||||
// Coefficients of the six clipping planes
|
||||
|
||||
GLStateManager.getMatrixMode()
|
||||
, GLStateManager.getNormalizeState()
|
||||
, GLStateManager.getRescaleNormalState()
|
||||
GLSMMatrices.getMatrixMode()
|
||||
, GLSMLighting.getNormalizeState()
|
||||
, GLSMLighting.getRescaleNormalState()
|
||||
));
|
||||
for(int i = 0; i < GLStateManager.getClipPlaneStates().length; i++) {
|
||||
transformAttribs.add(GLStateManager.getClipPlaneStates()[i]);
|
||||
for(int i = 0; i < GLSMRasterizer.getClipPlaneStates().length; i++) {
|
||||
transformAttribs.add(GLSMRasterizer.getClipPlaneStates()[i]);
|
||||
}
|
||||
attribToFeatures.put(GL11.GL_TRANSFORM_BIT, transformAttribs);
|
||||
attribToFeatures.put(GL11.GL_VIEWPORT_BIT, ImmutableSet.of(
|
||||
|
||||
GLStateManager.getViewportState()
|
||||
GLSMRasterizer.getViewportState()
|
||||
));
|
||||
|
||||
for (Int2ObjectMap.Entry<Set<IStateStack<?>>> entry : attribToFeatures.int2ObjectEntrySet()) {
|
||||
|
||||
@@ -121,7 +121,7 @@ public class FeedbackManager {
|
||||
final float ndcY = clipVec.y / w;
|
||||
final float ndcZ = clipVec.z / w;
|
||||
|
||||
final ViewportState vp = GLStateManager.getViewportState();
|
||||
final ViewportState vp = GLSMRasterizer.getViewportState();
|
||||
final float winX = vp.x + vp.width * (ndcX + 1.0f) * 0.5f;
|
||||
final float winY = vp.y + vp.height * (ndcY + 1.0f) * 0.5f;
|
||||
final float winZ = (float) ((vp.depthRangeFar - vp.depthRangeNear) * ndcZ + (vp.depthRangeFar + vp.depthRangeNear)) * 0.5f;
|
||||
@@ -229,7 +229,7 @@ public class FeedbackManager {
|
||||
}
|
||||
|
||||
private static void computeMVP() {
|
||||
mvpMatrix.set(GLStateManager.getProjectionMatrix()).mul(GLStateManager.getModelViewMatrix());
|
||||
mvpMatrix.set(GLSMMatrices.getProjectionMatrix()).mul(GLSMMatrices.getModelViewMatrix());
|
||||
}
|
||||
|
||||
private static int computeMask(int type) {
|
||||
@@ -277,13 +277,13 @@ public class FeedbackManager {
|
||||
final int previousVbo = glCtx.boundVBO;
|
||||
|
||||
if (positionVbo != 0 && positionVbo != previousVbo) {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, positionVbo);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, positionVbo);
|
||||
}
|
||||
try {
|
||||
RENDER_BACKEND.getBufferSubData(GL15.GL_ARRAY_BUFFER, offset, destination);
|
||||
} finally {
|
||||
if (positionVbo != 0 && positionVbo != previousVbo) {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, previousVbo);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, previousVbo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.stacks.IStateStack;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.AlphaStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BlendStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
@@ -58,6 +59,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GLContextState {
|
||||
final ExitStateCapture exitCapture = new ExitStateCapture(this);
|
||||
private final List<IStateStack<?>> allStacksBuilder = new ArrayList<>();
|
||||
public IStateStack<?>[] allStacks;
|
||||
final List<BooleanStateStack> allBooleanStates = new ArrayList<>();
|
||||
@@ -159,7 +161,7 @@ public class GLContextState {
|
||||
public final BooleanStateStack colorSumState = track(new BooleanStateStack(GL14.GL_COLOR_SUM, false, true));
|
||||
public final Color4Stack clearColor = member(new Color4Stack(StackIdAllocator.nextId(), new Color4(0.0F, 0.0F, 0.0F, 0.0F)).restoreBit(StateSet.R_CLEAR_COLOR));
|
||||
public final ColorMaskStack colorMask = member(new ColorMaskStack(StackIdAllocator.nextId()));
|
||||
public final IntegerStateStack drawBuffer = member(new IntegerStateStack(GLStateManager.DEFAULT_DRAW_BUFFER, StackIdAllocator.nextId()).restoreBit(StateSet.R_DRAW_BUFFER));
|
||||
public final IntegerStateStack drawBuffer = member(new IntegerStateStack(GLSMFramebuffer.DEFAULT_DRAW_BUFFER, StackIdAllocator.nextId()).restoreBit(StateSet.R_DRAW_BUFFER));
|
||||
public final IntegerStateStack logicOpMode = member(new IntegerStateStack(GL11.GL_COPY, StackIdAllocator.nextId()).restoreBit(StateSet.R_LOGIC_OP));
|
||||
public final BooleanStateStack cullState = track(new BooleanStateStack(GL11.GL_CULL_FACE));
|
||||
public final AlphaState restoredAlphaScratch = new AlphaState();
|
||||
@@ -243,12 +245,12 @@ public class GLContextState {
|
||||
public final int[] storageBufferBindings = new int[GLStateManager.INDEXED_BUFFER_SLOTS];
|
||||
public PixelStoreState pixelUnpackState = PixelStoreState.DEFAULT;
|
||||
public PixelStoreState pixelPackState = PixelStoreState.DEFAULT;
|
||||
public final int[] clientAttribSavedMask = new int[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final PixelStoreState[] clientAttribSavedPixelUnpack = new PixelStoreState[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
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 VAOManager.ClientArrays[] clientAttribSavedArrays = new VAOManager.ClientArrays[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final int[] clientAttribSavedMask = new int[GLSMAttribStack.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final PixelStoreState[] clientAttribSavedPixelUnpack = new PixelStoreState[GLSMAttribStack.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final PixelStoreState[] clientAttribSavedPixelPack = new PixelStoreState[GLSMAttribStack.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final int[] clientAttribSavedUnpackBuffer = new int[GLSMAttribStack.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final int[] clientAttribSavedPackBuffer = new int[GLSMAttribStack.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final VAOManager.ClientArrays[] clientAttribSavedArrays = new VAOManager.ClientArrays[GLSMAttribStack.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public int clientAttribStackPointer = 0;
|
||||
public int restoreChangedMask;
|
||||
public long restoreUnitChangedMask;
|
||||
@@ -257,6 +259,7 @@ public class GLContextState {
|
||||
public boolean vanillaBlendEnabledBefore;
|
||||
public int drawFramebuffer = 0;
|
||||
public int readFramebuffer = 0;
|
||||
public final Int2ObjectOpenHashMap<int[]> framebufferTextures = new Int2ObjectOpenHashMap<>();
|
||||
public int texGenGeneration;
|
||||
public int defaultVAO;
|
||||
public final VAOManager vaos = new VAOManager();
|
||||
@@ -272,6 +275,7 @@ public class GLContextState {
|
||||
public float savedFilterAniso = -1.0f;
|
||||
public boolean lineQuadsActive = false;
|
||||
public boolean lineStippleActive = false;
|
||||
public int textureSupersamplingSamples = 1;
|
||||
public Instancing ffpInstancing = Instancing.NONE;
|
||||
public float lastBrightnessX;
|
||||
public float lastBrightnessY;
|
||||
|
||||
@@ -11,11 +11,8 @@ public final class GLESCaps {
|
||||
|
||||
private GLESCaps() {}
|
||||
|
||||
public static boolean isCapAllowed(int cap, boolean isGLES, boolean hasClipCullDistance) {
|
||||
public static boolean isCapAllowed(int cap, boolean isGLES) {
|
||||
if (!isGLES) return true;
|
||||
if (cap >= GL11.GL_CLIP_PLANE0 && cap < GL11.GL_CLIP_PLANE0 + GLStateManager.MAX_CLIP_PLANES) {
|
||||
return hasClipCullDistance;
|
||||
}
|
||||
return switch (cap) {
|
||||
case GL11.GL_LINE_SMOOTH,
|
||||
GL11.GL_POLYGON_SMOOTH,
|
||||
|
||||
@@ -0,0 +1,667 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BlendStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.CowDepths;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.CowDispatch;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.CowStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.RetainedState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.AlphaState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.PixelStoreState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.SamplerUnitArray;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TextureBinding;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL21;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_ATTRIB_STACK_DEPTH;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_TEXTURE_UNITS;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.RETAINED_SLOT;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.primaryContext;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.warnOnce;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMAttribStack {
|
||||
|
||||
private GLSMAttribStack() {}
|
||||
|
||||
public static long attribPushes;
|
||||
public static long attribSlotsSaved;
|
||||
public static long attribValueRestores;
|
||||
public static long attribBackendCalls;
|
||||
public static long attribDiscards;
|
||||
|
||||
/** Register a state stack id as modified at the current depth (called from beforeModify). */
|
||||
public static void registerModifiedState(GLContextState c, int id) {
|
||||
if (c.attribDepth > 0) {
|
||||
final int depth = c.attribDepth - 1;
|
||||
c.modifiedIds[depth][c.modifiedCount[depth]++] = id;
|
||||
if (!c.poppingAttributes) {
|
||||
attribSlotsSaved++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final int CLIENT_ATTRIB_STACK_DEPTH = 16;
|
||||
public static void glPushClientAttrib(int mask) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final int sp = glCtx.clientAttribStackPointer;
|
||||
if (sp < CLIENT_ATTRIB_STACK_DEPTH) {
|
||||
glCtx.clientAttribSavedMask[sp] = mask;
|
||||
if ((mask & GL11.GL_CLIENT_PIXEL_STORE_BIT) != 0) {
|
||||
glCtx.clientAttribSavedPixelPack[sp] = glCtx.pixelPackState;
|
||||
glCtx.clientAttribSavedPixelUnpack[sp] = glCtx.pixelUnpackState;
|
||||
glCtx.clientAttribSavedPackBuffer[sp] = glCtx.boundPixelPackBuffer;
|
||||
glCtx.clientAttribSavedUnpackBuffer[sp] = glCtx.boundPixelUnpackBuffer;
|
||||
}
|
||||
if ((mask & GL11.GL_CLIENT_VERTEX_ARRAY_BIT) != 0) {
|
||||
VAOManager.ClientArrays saved = glCtx.clientAttribSavedArrays[sp];
|
||||
if (saved == null) glCtx.clientAttribSavedArrays[sp] = saved = new VAOManager.ClientArrays();
|
||||
saved.boundVAO = glCtx.boundVAO;
|
||||
saved.boundVBO = glCtx.boundVBO;
|
||||
saved.boundEBO = glCtx.vaos.boundEBO;
|
||||
saved.clientActiveTextureUnit = glCtx.clientActiveTextureUnit;
|
||||
glCtx.vaos.saveClientArrays(saved);
|
||||
}
|
||||
glCtx.clientAttribStackPointer = sp + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glPopClientAttrib() {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.clientAttribStackPointer > 0) {
|
||||
final int sp = --glCtx.clientAttribStackPointer;
|
||||
final int mask = glCtx.clientAttribSavedMask[sp];
|
||||
if ((mask & GL11.GL_CLIENT_PIXEL_STORE_BIT) != 0) {
|
||||
final PixelStoreState pack = glCtx.clientAttribSavedPixelPack[sp];
|
||||
final PixelStoreState unpack = glCtx.clientAttribSavedPixelUnpack[sp];
|
||||
glCtx.clientAttribSavedPixelPack[sp] = null;
|
||||
glCtx.clientAttribSavedPixelUnpack[sp] = null;
|
||||
PixelStoreState.applyDiff(glCtx.pixelPackState, pack, true);
|
||||
glCtx.pixelPackState = pack;
|
||||
PixelStoreState.applyDiff(glCtx.pixelUnpackState, unpack, false);
|
||||
glCtx.pixelUnpackState = unpack;
|
||||
final int packBuffer = glCtx.clientAttribSavedPackBuffer[sp];
|
||||
if (glCtx.boundPixelPackBuffer != packBuffer) GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, packBuffer);
|
||||
final int unpackBuffer = glCtx.clientAttribSavedUnpackBuffer[sp];
|
||||
if (glCtx.boundPixelUnpackBuffer != unpackBuffer) GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
|
||||
}
|
||||
if ((mask & GL11.GL_CLIENT_VERTEX_ARRAY_BIT) != 0) {
|
||||
restoreClientArrays(glCtx, glCtx.clientAttribSavedArrays[sp]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void restoreClientArrays(GLContextState glCtx, VAOManager.ClientArrays saved) {
|
||||
final VAOManager vaos = glCtx.vaos;
|
||||
if (!vaos.vaoMap.containsKey(saved.boundVAO)) return;
|
||||
GLSMVertexInput.bindVertexArrayInternal(glCtx, saved.boundVAO);
|
||||
glCtx.clientActiveTextureUnit = saved.clientActiveTextureUnit;
|
||||
if (vaos.isSavedVboLive(saved)) {
|
||||
final int changed = vaos.restoreClientArrays(saved);
|
||||
for (int pointers = changed & 0xFFFF; pointers != 0; pointers &= pointers - 1) {
|
||||
GLSMVertexInput.pointAttrib(glCtx, Integer.numberOfTrailingZeros(pointers));
|
||||
}
|
||||
for (int enables = changed >>> 16; enables != 0; enables &= enables - 1) {
|
||||
GLSMVertexInput.syncAttribEnable(glCtx, Integer.numberOfTrailingZeros(enables));
|
||||
}
|
||||
if (glCtx.boundVBO != saved.boundVBO) GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, saved.boundVBO);
|
||||
}
|
||||
if (vaos.boundEBO != saved.boundEBO && vaos.isSavedEboLive(saved)) GLSMBuffers.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, saved.boundEBO);
|
||||
}
|
||||
|
||||
public static void pushState(int mask) {
|
||||
pushStateLive(StateSet.forMask(mask));
|
||||
}
|
||||
|
||||
public static int pushState(StateSet set) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
final int token = ctx().attribDepth + DisplayListManager.virtualStateDepth(mode);
|
||||
if (token >= MAX_ATTRIB_STACK_DEPTH) {
|
||||
throw new IllegalStateException("Attrib stack overflow: max depth " + MAX_ATTRIB_STACK_DEPTH + " reached");
|
||||
}
|
||||
DisplayListManager.recordPushState(set);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
return pushStateLive(set);
|
||||
}
|
||||
|
||||
static int pushStateLive(StateSet set) {
|
||||
attribPushes++;
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.pushAttrib();
|
||||
if (glCtx.attribDepth >= MAX_ATTRIB_STACK_DEPTH) {
|
||||
throw new IllegalStateException("Attrib stack overflow: max depth " + MAX_ATTRIB_STACK_DEPTH + " reached");
|
||||
}
|
||||
final int depthBefore = glCtx.attribDepth;
|
||||
glCtx.attribSets[depthBefore] = set;
|
||||
glCtx.savedBatchStateGen[depthBefore] = glCtx.batchStateGeneration;
|
||||
|
||||
snapshotGenerations(glCtx, set.bump);
|
||||
|
||||
glCtx.modifiedCount[depthBefore] = 0;
|
||||
|
||||
if ((set.restore & StateSet.R_PROGRAM) != 0) {
|
||||
glCtx.programStack.setValue(glCtx.activeProgram);
|
||||
glCtx.programStack.push();
|
||||
attribSlotsSaved++;
|
||||
}
|
||||
|
||||
glCtx.attribDepth++;
|
||||
return depthBefore;
|
||||
}
|
||||
|
||||
private static void snapshotGenerations(GLContextState glCtx, int bump) {
|
||||
final int depth = glCtx.attribDepth;
|
||||
if ((bump & StateSet.B_LIGHTING) != 0) {
|
||||
glCtx.savedLightingGen[depth] = glCtx.lightingGeneration;
|
||||
}
|
||||
if ((bump & (StateSet.B_FRAG_COLORBUF | StateSet.B_FRAG_TEXTURE | StateSet.B_FRAG_FOG)) != 0) {
|
||||
glCtx.savedFragmentGen[depth] = glCtx.fragmentGeneration;
|
||||
}
|
||||
if ((bump & StateSet.B_TRANSFORM) != 0) {
|
||||
glCtx.savedMvGen[depth] = glCtx.mvGeneration;
|
||||
glCtx.savedMvLinearGen[depth] = glCtx.mvLinearGeneration;
|
||||
glCtx.savedProjGen[depth] = glCtx.projGeneration;
|
||||
glCtx.savedTexMatGen[depth] = glCtx.texMatrixGeneration;
|
||||
}
|
||||
if ((bump & StateSet.B_CURRENT) != 0) {
|
||||
glCtx.savedColorGen[depth] = glCtx.colorGeneration;
|
||||
glCtx.savedNormalGen[depth] = glCtx.ffp.normalGeneration;
|
||||
glCtx.savedTexCoordGen[depth] = glCtx.ffp.texCoordGeneration;
|
||||
}
|
||||
}
|
||||
|
||||
public static void popStateTo(int depth) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
while (glCtx.attribDepth + DisplayListManager.virtualStateDepth(mode) > depth) {
|
||||
if (mode == RecordMode.COMPILE && DisplayListManager.recordPopStateIfPending()) continue;
|
||||
if (mode == RecordMode.COMPILE_AND_EXECUTE) DisplayListManager.recordPopStateIfPending();
|
||||
popState();
|
||||
}
|
||||
}
|
||||
|
||||
public static void popState() {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.attribDepth > 0 && glCtx.savedBatchStateGen[glCtx.attribDepth - 1] != glCtx.batchStateGeneration) {
|
||||
beforeUncapturedStateChange();
|
||||
}
|
||||
final int poppedDepth = glCtx.attribDepth;
|
||||
final StateSet set = glCtx.attribSets[poppedDepth - 1];
|
||||
glCtx.exitCapture.popAttrib(set);
|
||||
final boolean inspectAlpha = GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()
|
||||
&& ((glCtx.alphaState.cowDepths().claimedAt(poppedDepth) && set.contains(glCtx.alphaState.stackId()))
|
||||
|| (glCtx.alphaTest.cowDepths().claimedAt(poppedDepth) && set.contains(glCtx.alphaTest.stackId())));
|
||||
final AlphaState effectiveAlpha = inspectAlpha ? glCtx.alphaState.readEffective(glCtx.restoredAlphaScratch) : null;
|
||||
final boolean effectiveEnabled = inspectAlpha && glCtx.alphaTest.isEffectivelyEnabled();
|
||||
final int effectiveFunction = inspectAlpha ? effectiveAlpha.getFunction() : 0;
|
||||
final float effectiveReference = inspectAlpha ? effectiveAlpha.getReference() : 0.0f;
|
||||
final boolean liveEnabled = inspectAlpha && glCtx.alphaTest.isEnabled();
|
||||
final int liveFunction = inspectAlpha ? glCtx.alphaState.getFunction() : 0;
|
||||
final float liveReference = inspectAlpha ? glCtx.alphaState.getReference() : 0.0f;
|
||||
final boolean prevPoppingAttributes = glCtx.poppingAttributes;
|
||||
glCtx.poppingAttributes = true;
|
||||
try {
|
||||
glCtx.attribDepth--;
|
||||
final int restore = set.restore;
|
||||
|
||||
final boolean blendSnapshotted = set.blendSnapshot
|
||||
&& (glCtx.blendState.cowDepths().claimedAt(poppedDepth) || glCtx.blendMode.cowDepths().claimedAt(poppedDepth))
|
||||
&& GLSMBlend.snapshotVanillaBlendFunc();
|
||||
|
||||
int changed = 0;
|
||||
long unitsChanged = 0L;
|
||||
|
||||
if ((restore & StateSet.R_PROGRAM) != 0) {
|
||||
glCtx.programStack.setValue(glCtx.activeProgram);
|
||||
if (glCtx.programStack.topSlotChanged()) changed |= StateSet.R_PROGRAM;
|
||||
glCtx.programStack.pop();
|
||||
}
|
||||
|
||||
final int depth = glCtx.attribDepth;
|
||||
final int count = glCtx.modifiedCount[depth];
|
||||
final int[] ids = glCtx.modifiedIds[depth];
|
||||
final CowStateStack<?>[] stackById = glCtx.stackById;
|
||||
final CowDepths[] depthsById = glCtx.depthsById;
|
||||
final int[] restoreBitById = glCtx.restoreBitById;
|
||||
final int[] restoreUnitById = glCtx.restoreUnitById;
|
||||
final byte[] kindById = glCtx.kindById;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
final int id = ids[i];
|
||||
final CowStateStack<?> cow = stackById[id];
|
||||
final byte kind = kindById[id];
|
||||
if (set.contains(id)) {
|
||||
final int bit = restoreBitById[id];
|
||||
if (bit != 0 && CowDispatch.topSlotChanged(kind, cow)) {
|
||||
changed |= bit;
|
||||
final int unit = restoreUnitById[id];
|
||||
if (unit >= 0) unitsChanged |= 1L << Math.min(unit, 63);
|
||||
}
|
||||
final int slot = depthsById[id].pop();
|
||||
if (slot >= 0) CowDispatch.restoreSlot(kind, cow, slot);
|
||||
if (bit == 0
|
||||
&& (kind == CowDispatch.BOOLEAN
|
||||
|| kind == CowDispatch.CLIP_PLANE_BOOLEAN
|
||||
|| kind == CowDispatch.TEXTURE_UNIT_BOOLEAN)) attribValueRestores++;
|
||||
} else {
|
||||
if (depthsById[id].discard(poppedDepth) >= 0) registerModifiedState(glCtx, id);
|
||||
attribDiscards++;
|
||||
}
|
||||
}
|
||||
glCtx.modifiedCount[depth] = 0;
|
||||
|
||||
glCtx.restoreChangedMask = changed;
|
||||
glCtx.restoreUnitChangedMask = unitsChanged;
|
||||
|
||||
applyRestoredState(set, blendSnapshotted);
|
||||
} finally {
|
||||
glCtx.poppingAttributes = prevPoppingAttributes;
|
||||
}
|
||||
if (inspectAlpha) {
|
||||
glCtx.alphaState.readEffective(glCtx.restoredAlphaScratch);
|
||||
if (effectiveEnabled != glCtx.alphaTest.isEffectivelyEnabled()
|
||||
|| effectiveFunction != effectiveAlpha.getFunction()
|
||||
|| Float.compare(effectiveReference, effectiveAlpha.getReference()) != 0
|
||||
|| liveEnabled != glCtx.alphaTest.isEnabled()
|
||||
|| liveFunction != glCtx.alphaState.getFunction()
|
||||
|| Float.compare(liveReference, glCtx.alphaState.getReference()) != 0) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void retainModifiedState(int depth, RetainedState out) {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (depth < 0 || depth != glCtx.attribDepth - 1) {
|
||||
throw new IllegalStateException("retainModifiedState: depth " + depth + " is not the open push (attrib depth " + glCtx.attribDepth + ")");
|
||||
}
|
||||
glCtx.retainedOwner = out;
|
||||
final int count = glCtx.modifiedCount[depth];
|
||||
final int[] ids = glCtx.modifiedIds[depth];
|
||||
final CowStateStack<?>[] stackById = glCtx.stackById;
|
||||
out.ensureCapacity(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
final int id = ids[i];
|
||||
stackById[id].captureSlot(RETAINED_SLOT);
|
||||
out.ids[i] = id;
|
||||
}
|
||||
out.count = count;
|
||||
out.program = glCtx.activeProgram;
|
||||
out.programGen = GLSMPrograms.programLifetimeGeneration;
|
||||
}
|
||||
|
||||
public static void applyRetainedState(RetainedState in) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.retainedOwner != in) return;
|
||||
final CowStateStack<?>[] stackById = glCtx.stackById;
|
||||
final byte[] kindById = glCtx.kindById;
|
||||
final int[] ids = in.ids;
|
||||
final int count = in.count;
|
||||
int first = 0;
|
||||
while (first < count && !CowDispatch.slotChanged(kindById[ids[first]], stackById[ids[first]], RETAINED_SLOT)) first++;
|
||||
if (first < count) applyRetainedChanges(glCtx, in, first);
|
||||
if (in.program != glCtx.activeProgram && (in.program == 0 || in.programGen == GLSMPrograms.programLifetimeGeneration)) GLSMPrograms.glUseProgram(in.program);
|
||||
}
|
||||
|
||||
private static void applyRetainedChanges(GLContextState glCtx, RetainedState in, int first) {
|
||||
beforeUncapturedStateChange();
|
||||
final boolean blendSnapshotted = GLSMBlend.snapshotVanillaBlendFunc();
|
||||
final int alphaFuncId = glCtx.alphaState.stackId();
|
||||
final int alphaTestId = glCtx.alphaTest.stackId();
|
||||
boolean alphaChanged = false;
|
||||
final boolean prevPoppingAttributes = glCtx.poppingAttributes;
|
||||
glCtx.poppingAttributes = true;
|
||||
try {
|
||||
final CowStateStack<?>[] stackById = glCtx.stackById;
|
||||
final int[] restoreBitById = glCtx.restoreBitById;
|
||||
final int[] restoreUnitById = glCtx.restoreUnitById;
|
||||
final byte[] kindById = glCtx.kindById;
|
||||
int changed = 0;
|
||||
long unitsChanged = 0L;
|
||||
for (int i = first; i < in.count; i++) {
|
||||
final int id = in.ids[i];
|
||||
final CowStateStack<?> cow = stackById[id];
|
||||
final byte kind = kindById[id];
|
||||
if (!CowDispatch.slotChanged(kind, cow, RETAINED_SLOT)) continue;
|
||||
cow.beforeModify();
|
||||
final int bit = restoreBitById[id];
|
||||
if (bit != 0) {
|
||||
changed |= bit;
|
||||
final int unit = restoreUnitById[id];
|
||||
if (unit >= 0) unitsChanged |= 1L << Math.min(unit, 63);
|
||||
}
|
||||
CowDispatch.restoreSlot(kind, cow, RETAINED_SLOT);
|
||||
if (id == alphaFuncId || id == alphaTestId) alphaChanged = true;
|
||||
}
|
||||
glCtx.restoreChangedMask = changed;
|
||||
glCtx.restoreUnitChangedMask = unitsChanged;
|
||||
issueRestoredBackendState(glCtx, -1);
|
||||
glCtx.lightingGeneration++;
|
||||
glCtx.fragmentGeneration++;
|
||||
glCtx.colorGeneration++;
|
||||
glCtx.ffp.normalGeneration++;
|
||||
glCtx.ffp.texCoordGeneration++;
|
||||
glCtx.dirtyColorAttrib = true;
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
GLSMBlend.postVanillaBlendChangeIfMoved(blendSnapshotted);
|
||||
} finally {
|
||||
glCtx.poppingAttributes = prevPoppingAttributes;
|
||||
}
|
||||
if (alphaChanged && GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDepthColorOverridden() {
|
||||
final DeferredDepthColorHandler dch = GLSMHooks.depthColorHandler;
|
||||
return dch != null && dch.isOverrideHeld();
|
||||
}
|
||||
|
||||
public static void replayStateToBackend() {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (RENDER_BACKEND == null) return;
|
||||
|
||||
final List<BooleanStateStack> booleanStates = glCtx.allBooleanStates;
|
||||
for (int i = 0; i < booleanStates.size(); i++) {
|
||||
booleanStates.get(i).applyToBackend();
|
||||
}
|
||||
|
||||
RENDER_BACKEND.depthFunc(glCtx.depthState.getFunc());
|
||||
RENDER_BACKEND.depthMask(glCtx.depthState.isEnabled());
|
||||
RENDER_BACKEND.clearDepth(glCtx.depthState.getClearValue());
|
||||
|
||||
GLSMBlend.issueBlendFunc(glCtx.blendState);
|
||||
glCtx.blendState.clearFuncUnknownState();
|
||||
RENDER_BACKEND.blendEquationSeparate(glCtx.blendState.getEquationRgb(), glCtx.blendState.getEquationAlpha());
|
||||
RENDER_BACKEND.blendColor(glCtx.blendState.getBlendColorR(), glCtx.blendState.getBlendColorG(), glCtx.blendState.getBlendColorB(), glCtx.blendState.getBlendColorA());
|
||||
RENDER_BACKEND.colorMask(glCtx.colorMask.red, glCtx.colorMask.green, glCtx.colorMask.blue, glCtx.colorMask.alpha);
|
||||
RENDER_BACKEND.clearColor(glCtx.clearColor.getRed(), glCtx.clearColor.getGreen(), glCtx.clearColor.getBlue(), glCtx.clearColor.getAlpha());
|
||||
RENDER_BACKEND.logicOp(glCtx.logicOpMode.getValue());
|
||||
|
||||
RENDER_BACKEND.stencilFuncSeparate(GL11.GL_FRONT, glCtx.stencilState.getFuncFront(), glCtx.stencilState.getRefFront(), glCtx.stencilState.getValueMaskFront());
|
||||
RENDER_BACKEND.stencilFuncSeparate(GL11.GL_BACK, glCtx.stencilState.getFuncBack(), glCtx.stencilState.getRefBack(), glCtx.stencilState.getValueMaskBack());
|
||||
RENDER_BACKEND.stencilOpSeparate(GL11.GL_FRONT, glCtx.stencilState.getFailOpFront(), glCtx.stencilState.getZFailOpFront(), glCtx.stencilState.getZPassOpFront());
|
||||
RENDER_BACKEND.stencilOpSeparate(GL11.GL_BACK, glCtx.stencilState.getFailOpBack(), glCtx.stencilState.getZFailOpBack(), glCtx.stencilState.getZPassOpBack());
|
||||
RENDER_BACKEND.stencilMaskSeparate(GL11.GL_FRONT, glCtx.stencilState.getWriteMaskFront());
|
||||
RENDER_BACKEND.stencilMaskSeparate(GL11.GL_BACK, glCtx.stencilState.getWriteMaskBack());
|
||||
RENDER_BACKEND.clearStencil(glCtx.stencilState.getClearValue());
|
||||
|
||||
RENDER_BACKEND.viewport(glCtx.viewportState.x, glCtx.viewportState.y, glCtx.viewportState.width, glCtx.viewportState.height);
|
||||
RENDER_BACKEND.depthRange(glCtx.viewportState.depthRangeNear, glCtx.viewportState.depthRangeFar);
|
||||
RENDER_BACKEND.scissor(glCtx.scissorState.x, glCtx.scissorState.y, glCtx.scissorState.width, glCtx.scissorState.height);
|
||||
RENDER_BACKEND.lineWidth(Math.clamp(glCtx.lineState.getWidth(), GLSMRasterizer.lineWidthMin, GLSMRasterizer.lineWidthMax));
|
||||
GLSMRasterizer.applyPointState(glCtx);
|
||||
GLSMRasterizer.applyHintState(glCtx);
|
||||
|
||||
RENDER_BACKEND.polygonMode(GL11.GL_FRONT_AND_BACK, glCtx.polygonState.getFrontMode());
|
||||
applyPolygonOffset(glCtx);
|
||||
RENDER_BACKEND.cullFace(glCtx.polygonState.getCullFaceMode());
|
||||
RENDER_BACKEND.frontFace(glCtx.polygonState.getFrontFace());
|
||||
|
||||
final SamplerUnitArray samplerUnits = glCtx.samplerUnits;
|
||||
for (int i = 0; i <= samplerUnits.getHighestBoundUnit(); i++) {
|
||||
final int sampler = samplerUnits.get(i);
|
||||
if (sampler != 0) RENDER_BACKEND.bindSampler(i, sampler);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= glCtx.maxBoundTextureUnit; i++) {
|
||||
final TextureBinding b = glCtx.textures.getTextureUnitBindings(i);
|
||||
RENDER_BACKEND.activeTexture(GL13.GL_TEXTURE0 + i);
|
||||
RENDER_BACKEND.bindTexture(b.getTarget() == 0 ? GL11.GL_TEXTURE_2D : b.getTarget(), b.getBinding());
|
||||
}
|
||||
RENDER_BACKEND.activeTexture(GL13.GL_TEXTURE0 + GLSMTextures.getActiveTextureUnit());
|
||||
if (glCtx.defaultVAO == 0 && primaryContext().defaultVAO != 0) glCtx.defaultVAO = RENDER_BACKEND.genVertexArrays();
|
||||
if (!glCtx.vaos.isInitialized()) glCtx.vaos.init(glCtx.defaultVAO);
|
||||
RENDER_BACKEND.bindVertexArray(glCtx.boundVAO != 0 ? glCtx.boundVAO : glCtx.defaultVAO);
|
||||
RENDER_BACKEND.useProgram(glCtx.activeProgram);
|
||||
glCtx.ffp.invalidateProgram();
|
||||
RENDER_BACKEND.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, glCtx.drawFramebuffer);
|
||||
RENDER_BACKEND.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, glCtx.readFramebuffer);
|
||||
glCtx.dirtyColorAttrib = true;
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
glCtx.dirtyLightmapAttrib = true;
|
||||
glCtx.dirtyEntityIdsAttrib = true;
|
||||
}
|
||||
|
||||
private static void applyPolygonOffset(GLContextState glCtx) {
|
||||
final float clamp = glCtx.polygonState.getOffsetClamp();
|
||||
if (clamp == 0.0f) {
|
||||
RENDER_BACKEND.polygonOffset(glCtx.polygonState.getOffsetFactor(), glCtx.polygonState.getOffsetUnits());
|
||||
} else {
|
||||
RENDER_BACKEND.polygonOffsetClamp(glCtx.polygonState.getOffsetFactor(), glCtx.polygonState.getOffsetUnits(), clamp);
|
||||
}
|
||||
}
|
||||
|
||||
private static void issueRestoredBackendState(GLContextState glCtx, int restore) {
|
||||
final int changed = glCtx.restoreChangedMask;
|
||||
if ((restore & StateSet.R_DEPTH) != 0 && (changed & StateSet.R_DEPTH) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.depthFunc(glCtx.depthState.getFunc());
|
||||
attribBackendCalls++;
|
||||
if (!isDepthColorOverridden()) {
|
||||
RENDER_BACKEND.depthMask(glCtx.depthState.isEnabled());
|
||||
attribBackendCalls++;
|
||||
}
|
||||
RENDER_BACKEND.clearDepth(glCtx.depthState.getClearValue());
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_BLEND) != 0) {
|
||||
final BlendStateStack blend = glCtx.blendState;
|
||||
if ((changed & StateSet.R_BLEND) != 0 || blend.isFuncUnknown()) {
|
||||
attribValueRestores++;
|
||||
final DeferredBlendHandler restoreBlendHandler = GLSMHooks.blendHandler;
|
||||
if (restoreBlendHandler == null || !restoreBlendHandler.isOverrideHeld()) {
|
||||
GLSMBlend.issueBlendFunc(blend);
|
||||
attribBackendCalls++;
|
||||
blend.clearFuncUnknownState();
|
||||
}
|
||||
if ((changed & StateSet.R_BLEND) != 0) {
|
||||
RENDER_BACKEND.blendEquationSeparate(blend.getEquationRgb(), blend.getEquationAlpha());
|
||||
attribBackendCalls++;
|
||||
RENDER_BACKEND.blendColor(
|
||||
blend.getBlendColorR(), blend.getBlendColorG(), blend.getBlendColorB(), blend.getBlendColorA());
|
||||
attribBackendCalls++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((restore & StateSet.R_COLOR_MASK) != 0 && (changed & StateSet.R_COLOR_MASK) != 0 && !isDepthColorOverridden()) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.colorMask(glCtx.colorMask.red, glCtx.colorMask.green, glCtx.colorMask.blue, glCtx.colorMask.alpha);
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_CLEAR_COLOR) != 0 && (changed & StateSet.R_CLEAR_COLOR) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.clearColor(glCtx.clearColor.getRed(), glCtx.clearColor.getGreen(), glCtx.clearColor.getBlue(), glCtx.clearColor.getAlpha());
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_DRAW_BUFFER) != 0 && (changed & StateSet.R_DRAW_BUFFER) != 0 && glCtx.drawFramebuffer == 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.drawBuffer(glCtx.drawBuffer.getValue());
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_LOGIC_OP) != 0 && (changed & StateSet.R_LOGIC_OP) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.logicOp(glCtx.logicOpMode.getValue());
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_STENCIL) != 0 && (changed & StateSet.R_STENCIL) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.stencilFuncSeparate(GL11.GL_FRONT, glCtx.stencilState.getFuncFront(), glCtx.stencilState.getRefFront(), glCtx.stencilState.getValueMaskFront());
|
||||
RENDER_BACKEND.stencilFuncSeparate(GL11.GL_BACK, glCtx.stencilState.getFuncBack(), glCtx.stencilState.getRefBack(), glCtx.stencilState.getValueMaskBack());
|
||||
RENDER_BACKEND.stencilOpSeparate(GL11.GL_FRONT, glCtx.stencilState.getFailOpFront(), glCtx.stencilState.getZFailOpFront(), glCtx.stencilState.getZPassOpFront());
|
||||
RENDER_BACKEND.stencilOpSeparate(GL11.GL_BACK, glCtx.stencilState.getFailOpBack(), glCtx.stencilState.getZFailOpBack(), glCtx.stencilState.getZPassOpBack());
|
||||
RENDER_BACKEND.stencilMaskSeparate(GL11.GL_FRONT, glCtx.stencilState.getWriteMaskFront());
|
||||
RENDER_BACKEND.stencilMaskSeparate(GL11.GL_BACK, glCtx.stencilState.getWriteMaskBack());
|
||||
RENDER_BACKEND.clearStencil(glCtx.stencilState.getClearValue());
|
||||
attribBackendCalls += 7;
|
||||
}
|
||||
if ((restore & StateSet.R_VIEWPORT) != 0 && (changed & StateSet.R_VIEWPORT) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.viewport(glCtx.viewportState.x, glCtx.viewportState.y, glCtx.viewportState.width, glCtx.viewportState.height);
|
||||
RENDER_BACKEND.depthRange(glCtx.viewportState.depthRangeNear, glCtx.viewportState.depthRangeFar);
|
||||
attribBackendCalls += 2;
|
||||
}
|
||||
if ((restore & StateSet.R_SCISSOR) != 0 && (changed & StateSet.R_SCISSOR) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.scissor(glCtx.scissorState.x, glCtx.scissorState.y, glCtx.scissorState.width, glCtx.scissorState.height);
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_LINE) != 0 && (changed & StateSet.R_LINE) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.lineWidth(Math.clamp(glCtx.lineState.getWidth(), GLSMRasterizer.lineWidthMin, GLSMRasterizer.lineWidthMax));
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_POINT) != 0 && (changed & StateSet.R_POINT) != 0) {
|
||||
attribValueRestores++;
|
||||
GLSMRasterizer.applyPointState(glCtx);
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_HINT) != 0 && (changed & StateSet.R_HINT) != 0) {
|
||||
attribValueRestores++;
|
||||
GLSMRasterizer.applyHintState(glCtx);
|
||||
attribBackendCalls++;
|
||||
}
|
||||
if ((restore & StateSet.R_POLYGON) != 0 && (changed & StateSet.R_POLYGON) != 0) {
|
||||
attribValueRestores++;
|
||||
RENDER_BACKEND.polygonMode(GL11.GL_FRONT_AND_BACK, glCtx.polygonState.getFrontMode());
|
||||
applyPolygonOffset(glCtx);
|
||||
RENDER_BACKEND.cullFace(glCtx.polygonState.getCullFaceMode());
|
||||
RENDER_BACKEND.frontFace(glCtx.polygonState.getFrontFace());
|
||||
attribBackendCalls += 4;
|
||||
}
|
||||
final boolean textureBitSet = (restore & StateSet.R_TEXTURE) != 0 && (changed & StateSet.R_TEXTURE) != 0;
|
||||
final boolean activeUnitBitSet = (restore & StateSet.R_ACTIVE_UNIT) != 0;
|
||||
if (textureBitSet || activeUnitBitSet) {
|
||||
boolean unitTouched = false;
|
||||
if (textureBitSet) {
|
||||
final long unitsChanged = glCtx.restoreUnitChangedMask;
|
||||
for (int i = 0; i < MAX_TEXTURE_UNITS; i++) {
|
||||
if ((unitsChanged & (1L << Math.min(i, 63))) != 0) {
|
||||
final TextureBinding restored = glCtx.textures.getTextureUnitBindings(i);
|
||||
final int restoredTarget = restored.getTarget() != 0 ? restored.getTarget() : GL11.GL_TEXTURE_2D;
|
||||
RENDER_BACKEND.activeTexture(GL13.GL_TEXTURE0 + i);
|
||||
RENDER_BACKEND.bindTexture(restoredTarget, restored.getBinding());
|
||||
attribValueRestores++;
|
||||
attribBackendCalls += 2;
|
||||
unitTouched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unitTouched || (activeUnitBitSet && (changed & StateSet.R_ACTIVE_UNIT) != 0)) {
|
||||
RENDER_BACKEND.activeTexture(GL13.GL_TEXTURE0 + glCtx.activeTextureUnit.getValue());
|
||||
attribValueRestores++;
|
||||
attribBackendCalls++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After popping GLSM stacks, apply restored state to the GL driver.
|
||||
*/
|
||||
private static void applyRestoredState(StateSet set, boolean blendSnapshotted) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final int restore = set.restore;
|
||||
final int changed = glCtx.restoreChangedMask;
|
||||
issueRestoredBackendState(glCtx, restore);
|
||||
|
||||
final int bump = set.bump;
|
||||
final int depth = glCtx.attribDepth;
|
||||
if ((bump & StateSet.B_LIGHTING) != 0 && glCtx.lightingGeneration != glCtx.savedLightingGen[depth]) glCtx.lightingGeneration++;
|
||||
if ((bump & StateSet.B_FRAG_FOG) != 0 && glCtx.fragmentGeneration != glCtx.savedFragmentGen[depth]) glCtx.fragmentGeneration++;
|
||||
if ((bump & StateSet.B_FRAG_COLORBUF) != 0 && glCtx.fragmentGeneration != glCtx.savedFragmentGen[depth]) glCtx.fragmentGeneration++;
|
||||
if ((bump & StateSet.B_FRAG_TEXTURE) != 0 && glCtx.fragmentGeneration != glCtx.savedFragmentGen[depth]) glCtx.fragmentGeneration++;
|
||||
if ((bump & StateSet.B_TRANSFORM) != 0) {
|
||||
if (glCtx.mvGeneration != glCtx.savedMvGen[depth]) glCtx.mvGeneration++;
|
||||
if (glCtx.mvLinearGeneration != glCtx.savedMvLinearGen[depth]) glCtx.mvLinearGeneration++;
|
||||
if (glCtx.projGeneration != glCtx.savedProjGen[depth]) glCtx.projGeneration++;
|
||||
if (glCtx.texMatrixGeneration != glCtx.savedTexMatGen[depth]) glCtx.texMatrixGeneration++;
|
||||
}
|
||||
if ((bump & StateSet.B_CURRENT) != 0) {
|
||||
if (glCtx.colorGeneration != glCtx.savedColorGen[depth]) {
|
||||
glCtx.colorGeneration++;
|
||||
glCtx.dirtyColorAttrib = true;
|
||||
}
|
||||
if (glCtx.ffp.normalGeneration != glCtx.savedNormalGen[depth]) {
|
||||
glCtx.ffp.normalGeneration++;
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
}
|
||||
if (glCtx.ffp.texCoordGeneration != glCtx.savedTexCoordGen[depth]) {
|
||||
glCtx.ffp.texCoordGeneration++;
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
if ((restore & StateSet.R_SECONDARY_COLOR) != 0 && (changed & StateSet.R_SECONDARY_COLOR) != 0) glCtx.fragmentGeneration++;
|
||||
}
|
||||
|
||||
GLSMBlend.postVanillaBlendChangeIfMoved(blendSnapshotted);
|
||||
|
||||
if ((restore & StateSet.R_PROGRAM) != 0 && (changed & StateSet.R_PROGRAM) != 0) {
|
||||
GLSMPrograms.glUseProgram(glCtx.programStack.getValue());
|
||||
attribValueRestores++;
|
||||
attribBackendCalls++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glPushAttrib(int mask) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordPushAttrib(mask);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
GLDebug.pushGroup("pushState");
|
||||
pushState(mask);
|
||||
}
|
||||
|
||||
public static void glPopAttrib() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordPopAttrib();
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ctx().attribDepth == 0) {
|
||||
rejectExitCapture();
|
||||
warnOnce("popattrib-underflow", "glPopAttrib called with an empty attrib stack; ignoring");
|
||||
return;
|
||||
}
|
||||
GLDebug.popGroup();
|
||||
GLDebug.pushGroup("popState");
|
||||
try {
|
||||
popState();
|
||||
} finally {
|
||||
GLDebug.popGroup();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPoppingAttributes() {
|
||||
return ctx().poppingAttributes;
|
||||
}
|
||||
|
||||
public static int getAttribDepth() {
|
||||
return ctx().attribDepth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BlendStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.Color4Stack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.ColorMaskStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.IntegerStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.BlendState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ColorMask;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMBlend {
|
||||
|
||||
private GLSMBlend() {}
|
||||
|
||||
public static void glBlendColor(float red, float green, float blue, float alpha) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordBlendColor(red, green, blue, alpha);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean bypass = !caching;
|
||||
if (bypass || red != glCtx.blendState.getBlendColorR() || green != glCtx.blendState.getBlendColorG() || blue != glCtx.blendState.getBlendColorB() || alpha != glCtx.blendState.getBlendColorA()) {
|
||||
mod(glCtx.blendState);
|
||||
beforeUncapturedStateChange();
|
||||
glCtx.blendState.setBlendColorR(red);
|
||||
glCtx.blendState.setBlendColorG(green);
|
||||
glCtx.blendState.setBlendColorB(blue);
|
||||
glCtx.blendState.setBlendColorA(alpha);
|
||||
RENDER_BACKEND.blendColor(red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glBlendFuncSeparatei(int buf, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.blendFuncSeparatei(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
ctx().blendState.setFuncUnknownState();
|
||||
}
|
||||
|
||||
public static void enableBlend() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_BLEND);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableBlend(ctx());
|
||||
}
|
||||
|
||||
static void enableBlend(GLContextState glCtx) {
|
||||
final BooleanStateStack blend = glCtx.blendMode;
|
||||
final boolean wasEnabled = blend.isEffectivelyEnabled();
|
||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||
if (bh != null && bh.isBlendLocked()) {
|
||||
glCtx.exitCapture.capability(GL11.GL_BLEND, -1);
|
||||
blend.beforeModify();
|
||||
bh.deferBlendModeToggle(true);
|
||||
} else {
|
||||
blend.enable();
|
||||
}
|
||||
if (!wasEnabled && blend.isEffectivelyEnabled()) postVanillaBlendChange();
|
||||
}
|
||||
|
||||
public static void disableBlend() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_BLEND);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableBlend(ctx());
|
||||
}
|
||||
|
||||
static void disableBlend(GLContextState glCtx) {
|
||||
final BooleanStateStack blend = glCtx.blendMode;
|
||||
final boolean wasEnabled = blend.isEffectivelyEnabled();
|
||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||
if (bh != null && bh.isBlendLocked()) {
|
||||
glCtx.exitCapture.capability(GL11.GL_BLEND, -1);
|
||||
blend.beforeModify();
|
||||
bh.deferBlendModeToggle(false);
|
||||
} else {
|
||||
blend.disable();
|
||||
}
|
||||
if (wasEnabled && !blend.isEffectivelyEnabled()) postVanillaBlendChange();
|
||||
}
|
||||
|
||||
private static void postVanillaBlendChange() {
|
||||
if (GLSMHooks.VANILLA_BLEND_CHANGE.hasListeners()) {
|
||||
GLSMHooks.VANILLA_BLEND_CHANGE.post(GLSMHooks.vanillaBlendChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean snapshotVanillaBlendFunc() {
|
||||
if (!GLSMHooks.VANILLA_BLEND_CHANGE.hasListeners()) return false;
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.blendState.readEffective(glCtx.vanillaBlendBefore);
|
||||
glCtx.vanillaBlendEnabledBefore = glCtx.blendMode.isEffectivelyEnabled();
|
||||
return true;
|
||||
}
|
||||
|
||||
static void postVanillaBlendChangeIfMoved(boolean snapshotted) {
|
||||
if (!snapshotted) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
final BlendState before = glCtx.vanillaBlendBefore;
|
||||
final BlendState after = glCtx.blendState.readEffective(glCtx.vanillaBlendAfter);
|
||||
if (glCtx.blendMode.isEffectivelyEnabled() != glCtx.vanillaBlendEnabledBefore
|
||||
|| after.getSrcRgb() != before.getSrcRgb()
|
||||
|| after.getDstRgb() != before.getDstRgb()
|
||||
|| after.getSrcAlpha() != before.getSrcAlpha()
|
||||
|| after.getDstAlpha() != before.getDstAlpha()) {
|
||||
postVanillaBlendChange();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEffectiveBlendEnabled() {
|
||||
return ctx().blendMode.isEffectivelyEnabled();
|
||||
}
|
||||
|
||||
public static BlendState getEffectiveBlendState(BlendState out) {
|
||||
return ctx().blendState.readEffective(out);
|
||||
}
|
||||
|
||||
public static ColorMask getEffectiveColorMask(ColorMask out) {
|
||||
return ctx().colorMask.readEffective(out);
|
||||
}
|
||||
|
||||
public static void glBlendFunc(int srcFactor, int dstFactor) {
|
||||
tryBlendFuncSeparate(srcFactor, dstFactor, srcFactor, dstFactor);
|
||||
}
|
||||
|
||||
static void issueBlendFunc(BlendStateStack blend) {
|
||||
if (GLSMConfig.hudCacheOverride) {
|
||||
RENDER_BACKEND.blendFuncSeparate(blend.getSrcRgb(), blend.getDstRgb(), GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
RENDER_BACKEND.blendFuncSeparate(blend.getSrcRgb(), blend.getDstRgb(), blend.getSrcAlpha(), blend.getDstAlpha());
|
||||
}
|
||||
}
|
||||
|
||||
public static void setHudCacheOverride(boolean enabled) {
|
||||
if (GLSMConfig.hudCacheOverride == enabled) return;
|
||||
GLSMConfig.hudCacheOverride = enabled;
|
||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||
if (bh != null && bh.isOverrideHeld()) return;
|
||||
final BlendStateStack blend = ctx().blendState;
|
||||
issueBlendFunc(blend);
|
||||
blend.clearFuncUnknownState();
|
||||
}
|
||||
|
||||
public static void glBlendEquation(int mode) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw DisplayListManager.unsupportedInList("glBlendEquation");
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean bypass = !caching;
|
||||
if (bypass || glCtx.blendState.getEquationRgb() != mode || glCtx.blendState.getEquationAlpha() != mode) {
|
||||
mod(glCtx.blendState);
|
||||
beforeUncapturedStateChange();
|
||||
glCtx.blendState.setEquationRgb(mode);
|
||||
glCtx.blendState.setEquationAlpha(mode);
|
||||
RENDER_BACKEND.blendEquation(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glBlendEquationSeparate(int modeRGB, int modeAlpha) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw DisplayListManager.unsupportedInList("glBlendEquationSeparate");
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean bypass = !caching;
|
||||
if (bypass || glCtx.blendState.getEquationRgb() != modeRGB || glCtx.blendState.getEquationAlpha() != modeAlpha) {
|
||||
mod(glCtx.blendState);
|
||||
beforeUncapturedStateChange();
|
||||
glCtx.blendState.setEquationRgb(modeRGB);
|
||||
glCtx.blendState.setEquationAlpha(modeAlpha);
|
||||
RENDER_BACKEND.blendEquationSeparate(modeRGB, modeAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
public static void tryBlendFuncSeparate(int srcRgb, int dstRgb, int srcAlpha, int dstAlpha) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.writeBlend();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordBlendFunc(srcRgb, dstRgb, srcAlpha, dstAlpha);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean snapshotted = snapshotVanillaBlendFunc();
|
||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||
if (bh != null && bh.isBlendLocked()) {
|
||||
mod(glCtx.blendState);
|
||||
bh.deferBlendFunc(srcRgb, dstRgb, srcAlpha, dstAlpha);
|
||||
postVanillaBlendChangeIfMoved(snapshotted);
|
||||
return;
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean bypass = !caching;
|
||||
if (bypass || glCtx.blendState.getSrcRgb() != srcRgb || glCtx.blendState.getDstRgb() != dstRgb || glCtx.blendState.getSrcAlpha() != srcAlpha || glCtx.blendState.getDstAlpha() != dstAlpha || glCtx.blendState.isFuncUnknown()) {
|
||||
mod(glCtx.blendState);
|
||||
glCtx.blendState.setAll(srcRgb, dstRgb, srcAlpha, dstAlpha);
|
||||
glCtx.blendState.clearFuncUnknownState();
|
||||
issueBlendFunc(glCtx.blendState);
|
||||
if (GLSMHooks.BLEND_FUNC_CHANGE.hasListeners()) {
|
||||
final boolean hudCache = GLSMConfig.hudCacheOverride;
|
||||
GLSMHooks.blendFuncChangeEvent.srcRgb = srcRgb;
|
||||
GLSMHooks.blendFuncChangeEvent.dstRgb = dstRgb;
|
||||
GLSMHooks.blendFuncChangeEvent.srcAlpha = hudCache ? GL11.GL_ONE : srcAlpha;
|
||||
GLSMHooks.blendFuncChangeEvent.dstAlpha = hudCache ? GL11.GL_ONE_MINUS_SRC_ALPHA : dstAlpha;
|
||||
GLSMHooks.BLEND_FUNC_CHANGE.post(GLSMHooks.blendFuncChangeEvent);
|
||||
}
|
||||
}
|
||||
postVanillaBlendChangeIfMoved(snapshotted);
|
||||
}
|
||||
|
||||
public static void glBlendFuncSeparate(int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) {
|
||||
tryBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
public static void glColorMask(boolean red, boolean green, boolean blue, boolean alpha) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.writeDepthColor(ExitStateCapture.COLOR_MASK);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColorMask(red, green, blue, alpha);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final DeferredDepthColorHandler dch = GLSMHooks.depthColorHandler;
|
||||
if (dch != null && dch.isDepthColorLocked()) {
|
||||
mod(glCtx.colorMask);
|
||||
dch.deferColorMask(red, green, blue, alpha);
|
||||
return;
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean bypass = !caching;
|
||||
if (bypass || red != glCtx.colorMask.red || green != glCtx.colorMask.green || blue != glCtx.colorMask.blue || alpha != glCtx.colorMask.alpha) {
|
||||
mod(glCtx.colorMask);
|
||||
glCtx.colorMask.setAll(red, green, blue, alpha);
|
||||
RENDER_BACKEND.colorMask(red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glClearColor(float red, float green, float blue, float alpha) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordClearColor(red, green, blue, alpha);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || red != glCtx.clearColor.getRed() || green != glCtx.clearColor.getGreen() || blue != glCtx.clearColor.getBlue() || alpha != glCtx.clearColor.getAlpha()) {
|
||||
mod(glCtx.clearColor);
|
||||
glCtx.clearColor.setRed(red);
|
||||
glCtx.clearColor.setGreen(green);
|
||||
glCtx.clearColor.setBlue(blue);
|
||||
glCtx.clearColor.setAlpha(alpha);
|
||||
RENDER_BACKEND.clearColor(red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLogicOp(int opcode) {
|
||||
rejectExitCapture();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLogicOp(opcode);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isCachingEnabled() || ctx().logicOpMode.getValue() != opcode) beforeUncapturedStateChange();
|
||||
if (isCachingEnabled()) mod(ctx().logicOpMode).setValue(opcode);
|
||||
RENDER_BACKEND.logicOp(opcode);
|
||||
}
|
||||
|
||||
public static void defaultBlendFunc() {
|
||||
tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
|
||||
public static BlendStateStack getBlendState() {
|
||||
return ctx().blendState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getBlendMode() {
|
||||
return ctx().blendMode;
|
||||
}
|
||||
|
||||
public static Color4Stack getClearColor() {
|
||||
return ctx().clearColor;
|
||||
}
|
||||
|
||||
public static ColorMaskStack getColorMask() {
|
||||
return ctx().colorMask;
|
||||
}
|
||||
|
||||
public static IntegerStateStack getLogicOpMode() {
|
||||
return ctx().logicOpMode;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getColorLogicOpState() {
|
||||
return ctx().colorLogicOpState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getIndexLogicOpState() {
|
||||
return ctx().indexLogicOpState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,631 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.FfpExtendedAttribs;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL21;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.opengl.GL43;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.LongBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.INDEXED_BUFFER_SLOTS;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.LOGGER;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.acquireDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.initConfig;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.releaseDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.requireContext;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMBuffers {
|
||||
|
||||
private GLSMBuffers() {}
|
||||
|
||||
private static final IntOpenHashSet writeMappedBuffers = new IntOpenHashSet();
|
||||
|
||||
public static void glDeleteBuffers(int buffer) {
|
||||
rejectExitCapture();
|
||||
if (buffer == 0) return;
|
||||
invalidateDeletedBuffer(buffer);
|
||||
RENDER_BACKEND.deleteBuffers(buffer);
|
||||
}
|
||||
|
||||
public static void glDeleteSync(long sync) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.deleteSync(sync);
|
||||
}
|
||||
|
||||
public static long glFenceSync(int condition, int flags) { rejectExitCapture(); return RENDER_BACKEND.fenceSync(condition, flags); }
|
||||
public static int glClientWaitSync(long sync, int flags, long timeout) { rejectExitCapture(); return RENDER_BACKEND.clientWaitSync(sync, flags, timeout); }
|
||||
public static void glWaitSync(long sync, int flags, long timeout) { rejectExitCapture(); RENDER_BACKEND.waitSync(sync, flags, timeout); }
|
||||
public static int glGetSynci(long sync, int pname, IntBuffer length) { rejectExitCapture(); return RENDER_BACKEND.getSynci(sync, pname, length); }
|
||||
|
||||
public static void glDeleteBuffers(IntBuffer buffers) {
|
||||
rejectExitCapture();
|
||||
for (int i = buffers.position(); i < buffers.limit(); i++) {
|
||||
invalidateDeletedBuffer(buffers.get(i));
|
||||
}
|
||||
RENDER_BACKEND.deleteBuffers(buffers);
|
||||
}
|
||||
|
||||
public static void glDeleteBuffers(int[] buffers) {
|
||||
for (int buffer : buffers) {
|
||||
glDeleteBuffers(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static long bufferDeletes;
|
||||
|
||||
private static void invalidateDeletedBuffer(int buffer) {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (buffer == 0) return;
|
||||
bufferDeletes++;
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
FfpExtendedAttribs.onDeleteBuffer(glCtx, buffer);
|
||||
if (glCtx.boundVBO == buffer) glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
if (glCtx.vaos.boundEBO == buffer) glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (glCtx.boundPixelUnpackBuffer == buffer) glBindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
if (glCtx.boundPixelPackBuffer == buffer) glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
|
||||
if (glCtx.boundCopyReadBuffer == buffer) glBindBuffer(GL31.GL_COPY_READ_BUFFER, 0);
|
||||
if (glCtx.boundCopyWriteBuffer == buffer) glBindBuffer(GL31.GL_COPY_WRITE_BUFFER, 0);
|
||||
for (Int2IntMap.Entry e : glCtx.boundOtherBuffers.int2IntEntrySet()) {
|
||||
if (e.getIntValue() != buffer) continue;
|
||||
e.setValue(0);
|
||||
RENDER_BACKEND.bindBuffer(e.getIntKey(), 0);
|
||||
}
|
||||
for (int i = 0; i < INDEXED_BUFFER_SLOTS; i++) {
|
||||
if (glCtx.uniformBufferBindings[i] == buffer) glCtx.uniformBufferBindings[i] = 0;
|
||||
if (glCtx.storageBufferBindings[i] == buffer) glCtx.storageBufferBindings[i] = 0;
|
||||
}
|
||||
writeMappedBuffers.remove(buffer);
|
||||
|
||||
glCtx.vaos.onDeleteBuffer(buffer, glCtx.clientAttribSavedArrays);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
/** glBindBufferBase/Range also set the generic binding point, so they share this. */
|
||||
private static void trackBufferBinding(GLContextState glCtx, int target, int buffer) {
|
||||
if (target == GL15.GL_ARRAY_BUFFER) {
|
||||
// if (boundVBO == buffer) return; TODO figure out why this breaks switching async occlusion mode
|
||||
glCtx.boundVBO = buffer;
|
||||
} else if (target == GL15.GL_ELEMENT_ARRAY_BUFFER) {
|
||||
glCtx.vaos.onBindEBO(buffer);
|
||||
} else if (target == GL21.GL_PIXEL_UNPACK_BUFFER) {
|
||||
glCtx.boundPixelUnpackBuffer = buffer;
|
||||
} else if (target == GL21.GL_PIXEL_PACK_BUFFER) {
|
||||
glCtx.boundPixelPackBuffer = buffer;
|
||||
} else if (target == GL31.GL_COPY_READ_BUFFER) {
|
||||
glCtx.boundCopyReadBuffer = buffer;
|
||||
} else if (target == GL31.GL_COPY_WRITE_BUFFER) {
|
||||
glCtx.boundCopyWriteBuffer = buffer;
|
||||
} else {
|
||||
glCtx.boundOtherBuffers.put(target, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glBindBuffer(int target, int buffer) {
|
||||
rejectExitCapture();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
trackBufferBinding(ctx(), target, buffer);
|
||||
RENDER_BACKEND.bindBuffer(target, buffer);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean warnedUntrackedPixelBuffer;
|
||||
|
||||
private static void warnUntrackedPixelBuffer(int binding, String name) {
|
||||
if (warnedUntrackedPixelBuffer || initConfig == null || !initConfig.isLwjglDebug()) return;
|
||||
final int actual = RENDER_BACKEND.getInteger(binding);
|
||||
if (actual == 0) return;
|
||||
warnedUntrackedPixelBuffer = true;
|
||||
LOGGER.warn("{} is bound to {} but GLSM's cache says 0; a call site bypassed GLSMBuffers.glBindBuffer", name, actual, new Throwable());
|
||||
}
|
||||
|
||||
static void suspendPixelUnpackBuffer() {
|
||||
if (ctx().boundPixelUnpackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
} else {
|
||||
warnUntrackedPixelBuffer(GL21.GL_PIXEL_UNPACK_BUFFER_BINDING, "GL_PIXEL_UNPACK_BUFFER");
|
||||
}
|
||||
}
|
||||
|
||||
static void restorePixelUnpackBuffer() {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.boundPixelUnpackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, glCtx.boundPixelUnpackBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void suspendPixelPackBuffer() {
|
||||
if (ctx().boundPixelPackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
|
||||
} else {
|
||||
warnUntrackedPixelBuffer(GL21.GL_PIXEL_PACK_BUFFER_BINDING, "GL_PIXEL_PACK_BUFFER");
|
||||
}
|
||||
}
|
||||
|
||||
static void restorePixelPackBuffer() {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.boundPixelPackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_PACK_BUFFER, glCtx.boundPixelPackBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public static int glGenBuffers() {
|
||||
requireContext("glGenBuffers");
|
||||
return RENDER_BACKEND.genBuffers();
|
||||
}
|
||||
|
||||
public static void glGenBuffers(IntBuffer buffers) {
|
||||
requireContext("glGenBuffers");
|
||||
for (int i = buffers.position(); i < buffers.limit(); i++) buffers.put(i, RENDER_BACKEND.genBuffers());
|
||||
}
|
||||
|
||||
public static void glGenBuffers(int[] buffers) {
|
||||
requireContext("glGenBuffers");
|
||||
for (int i = 0; i < buffers.length; i++) buffers[i] = RENDER_BACKEND.genBuffers();
|
||||
}
|
||||
|
||||
public static int glCreateBuffers() {
|
||||
requireContext("glCreateBuffers");
|
||||
return RENDER_BACKEND.createBuffers();
|
||||
}
|
||||
|
||||
public static void glCreateBuffers(IntBuffer buffers) {
|
||||
requireContext("glCreateBuffers");
|
||||
for (int i = buffers.position(); i < buffers.limit(); i++) buffers.put(i, RENDER_BACKEND.createBuffers());
|
||||
}
|
||||
|
||||
public static void glCreateBuffers(int[] buffers) {
|
||||
requireContext("glCreateBuffers");
|
||||
for (int i = 0; i < buffers.length; i++) buffers[i] = RENDER_BACKEND.createBuffers();
|
||||
}
|
||||
|
||||
private static final int MAP_PERSISTENT_BIT = 0x40;
|
||||
|
||||
private static int bufferForTarget(GLContextState glCtx, int target) {
|
||||
if (target == GL15.GL_ARRAY_BUFFER) return glCtx.boundVBO;
|
||||
if (target == GL15.GL_ELEMENT_ARRAY_BUFFER) return glCtx.vaos.boundEBO;
|
||||
if (target == GL31.GL_COPY_READ_BUFFER) return glCtx.boundCopyReadBuffer;
|
||||
if (target == GL31.GL_COPY_WRITE_BUFFER) return glCtx.boundCopyWriteBuffer;
|
||||
if (target == GL21.GL_PIXEL_UNPACK_BUFFER) return glCtx.boundPixelUnpackBuffer;
|
||||
if (target == GL21.GL_PIXEL_PACK_BUFFER) return glCtx.boundPixelPackBuffer;
|
||||
return glCtx.boundOtherBuffers.get(target);
|
||||
}
|
||||
|
||||
private static void onBufferRespec(int target) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final int buffer = bufferForTarget(glCtx, target);
|
||||
if (buffer != 0) onNamedBufferRespec(glCtx, buffer);
|
||||
}
|
||||
|
||||
private static void onNamedBufferRespec(GLContextState glCtx, int buffer) {
|
||||
rejectExitCapture();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (!FfpExtendedAttribs.isEmpty()) FfpExtendedAttribs.onBufferRespecified(glCtx, buffer);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void onBufferMap(int target, int access) {
|
||||
if (access == GL15.GL_READ_ONLY) return;
|
||||
onBufferWriteMap(target);
|
||||
}
|
||||
|
||||
private static void onBufferMapRange(int target, int access) {
|
||||
if ((access & GL30.GL_MAP_WRITE_BIT) == 0) return;
|
||||
if ((access & MAP_PERSISTENT_BIT) != 0) {
|
||||
markPersistentlyMapped(target);
|
||||
return;
|
||||
}
|
||||
onBufferWriteMap(target);
|
||||
}
|
||||
|
||||
private static void onBufferWriteMap(int target) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final int buffer = bufferForTarget(glCtx, target);
|
||||
if (buffer == 0) return;
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
writeMappedBuffers.add(buffer);
|
||||
if (!FfpExtendedAttribs.isEmpty()) FfpExtendedAttribs.onBufferRespecified(glCtx, buffer);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void onBufferUnmap(int target) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final int buffer = bufferForTarget(glCtx, target);
|
||||
if (buffer == 0) return;
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (writeMappedBuffers.remove(buffer) && !FfpExtendedAttribs.isEmpty()) FfpExtendedAttribs.onBufferRespecified(glCtx, buffer);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void onBufferStorage(int target, int flags) {
|
||||
rejectExitCapture();
|
||||
if ((flags & MAP_PERSISTENT_BIT) != 0) {
|
||||
if (!RENDER_BACKEND.isBufferImmutable(bufferForTarget(ctx(), target))) markPersistentlyMapped(target);
|
||||
return;
|
||||
}
|
||||
onBufferRespec(target);
|
||||
}
|
||||
|
||||
private static void markPersistentlyMapped(int target) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
FfpExtendedAttribs.markPersistent(glCtx, bufferForTarget(glCtx, target));
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glBufferData(int target, long size, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, size, usage); }
|
||||
public static void glBufferData(int target, ByteBuffer data, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, ShortBuffer data, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, IntBuffer data, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, FloatBuffer data, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, DoubleBuffer data, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, LongBuffer data, int usage) { glBufferData(target, MemoryUtilities.memByteBuffer(data), usage); }
|
||||
public static void glBufferData(int target, int[] data, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, float[] data, int usage) { onBufferRespec(target); RENDER_BACKEND.bufferData(target, data, usage); }
|
||||
public static void glBufferData(int target, short[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferData(target, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferData(int target, long[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferData(target, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferData(int target, double[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferData(target, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
|
||||
public static void nglBufferData(int target, long size, long data, int usage) {
|
||||
if (data == 0L) {
|
||||
glBufferData(target, size, usage);
|
||||
return;
|
||||
}
|
||||
glBufferData(target, MemoryUtilities.memByteBuffer(data, checkedSize(size)), usage);
|
||||
}
|
||||
|
||||
public static void glBufferSubData(int target, long offset, ByteBuffer data) { onBufferRespec(target); RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, ShortBuffer data) { onBufferRespec(target); RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, IntBuffer data) { onBufferRespec(target); RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, FloatBuffer data) { onBufferRespec(target); RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, DoubleBuffer data) { onBufferRespec(target); RENDER_BACKEND.bufferSubData(target, offset, data); }
|
||||
public static void glBufferSubData(int target, long offset, LongBuffer data) { glBufferSubData(target, offset, MemoryUtilities.memByteBuffer(data)); }
|
||||
public static void glBufferSubData(int target, long offset, short[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferSubData(target, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferSubData(int target, long offset, int[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferSubData(target, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferSubData(int target, long offset, long[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferSubData(target, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferSubData(int target, long offset, float[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferSubData(target, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferSubData(int target, long offset, double[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferSubData(target, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
|
||||
public static void nglBufferSubData(int target, long offset, long size, long data) { glBufferSubData(target, offset, MemoryUtilities.memByteBuffer(data, checkedSize(size))); }
|
||||
|
||||
public static ByteBuffer glMapBuffer(int target, int access) {
|
||||
rejectExitCapture();
|
||||
final ByteBuffer buf = RENDER_BACKEND.mapBuffer(target, access);
|
||||
if (buf != null) onBufferMap(target, access);
|
||||
return buf;
|
||||
}
|
||||
public static ByteBuffer glMapBuffer(int target, int access, ByteBuffer old_buffer) { return glMapBuffer(target, access); }
|
||||
public static ByteBuffer glMapBuffer(int target, int access, long length, ByteBuffer old_buffer) {
|
||||
rejectExitCapture();
|
||||
final ByteBuffer buf = RENDER_BACKEND.mapBuffer(target, access, length, old_buffer);
|
||||
if (buf != null) onBufferMap(target, access);
|
||||
return buf;
|
||||
}
|
||||
public static ByteBuffer glMapBufferRange(int target, long offset, long length, int access) {
|
||||
rejectExitCapture();
|
||||
final ByteBuffer buf = RENDER_BACKEND.mapBufferRange(target, offset, length, access);
|
||||
if (buf != null) onBufferMapRange(target, access);
|
||||
return buf;
|
||||
}
|
||||
public static ByteBuffer glMapBufferRange(int target, long offset, long length, int access, ByteBuffer old_buffer) { return glMapBufferRange(target, offset, length, access); }
|
||||
public static long glMapBufferRangeAddress(int target, long offset, long length, int access) {
|
||||
rejectExitCapture();
|
||||
final long address = RENDER_BACKEND.mapBufferRangeAddress(target, offset, length, access);
|
||||
if (address != 0L) onBufferMapRange(target, access);
|
||||
return address;
|
||||
}
|
||||
public static void glFlushMappedBufferRange(int target, long offset, long length) { rejectExitCapture(); RENDER_BACKEND.flushMappedBufferRange(target, offset, length); }
|
||||
public static boolean glUnmapBuffer(int target) {
|
||||
rejectExitCapture();
|
||||
onBufferUnmap(target);
|
||||
return RENDER_BACKEND.unmapBuffer(target);
|
||||
}
|
||||
|
||||
public static void glGetBufferSubData(int target, long offset, ByteBuffer data) { rejectExitCapture(); RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, ShortBuffer data) { rejectExitCapture(); RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, IntBuffer data) { rejectExitCapture(); RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, FloatBuffer data) { rejectExitCapture(); RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, DoubleBuffer data) { rejectExitCapture(); RENDER_BACKEND.getBufferSubData(target, offset, data); }
|
||||
public static void glGetBufferSubData(int target, long offset, LongBuffer data) { glGetBufferSubData(target, offset, MemoryUtilities.memByteBuffer(data)); }
|
||||
public static void glGetBufferSubData(int target, long offset, short[] data) {
|
||||
final ByteBuffer copy = MemoryUtilities.memAlloc(data.length << 1);
|
||||
glGetBufferSubData(target, offset, copy);
|
||||
copy.asShortBuffer().get(data);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glGetBufferSubData(int target, long offset, int[] data) {
|
||||
final ByteBuffer copy = MemoryUtilities.memAlloc(data.length << 2);
|
||||
glGetBufferSubData(target, offset, copy);
|
||||
copy.asIntBuffer().get(data);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glGetBufferSubData(int target, long offset, long[] data) {
|
||||
final ByteBuffer copy = MemoryUtilities.memAlloc(data.length << 3);
|
||||
glGetBufferSubData(target, offset, copy);
|
||||
copy.asLongBuffer().get(data);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glGetBufferSubData(int target, long offset, float[] data) {
|
||||
final ByteBuffer copy = MemoryUtilities.memAlloc(data.length << 2);
|
||||
glGetBufferSubData(target, offset, copy);
|
||||
copy.asFloatBuffer().get(data);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glGetBufferSubData(int target, long offset, double[] data) {
|
||||
final ByteBuffer copy = MemoryUtilities.memAlloc(data.length << 3);
|
||||
glGetBufferSubData(target, offset, copy);
|
||||
copy.asDoubleBuffer().get(data);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
|
||||
public static void nglGetBufferSubData(int target, long offset, long size, long data) { glGetBufferSubData(target, offset, MemoryUtilities.memByteBuffer(data, checkedSize(size))); }
|
||||
|
||||
public static int glGetBufferParameteri(int target, int pname) { rejectExitCapture(); return RENDER_BACKEND.getBufferParameteri(target, pname); }
|
||||
public static int glGetBufferParameter(int target, int pname) { return glGetBufferParameteri(target, pname); }
|
||||
public static void glGetBufferParameter(int target, int pname, IntBuffer params) { params.put(params.position(), glGetBufferParameteri(target, pname)); }
|
||||
public static void glGetBufferParameteriv(int target, int pname, IntBuffer params) { params.put(params.position(), glGetBufferParameteri(target, pname)); }
|
||||
public static void glGetBufferParameteriv(int target, int pname, int[] params) { params[0] = glGetBufferParameteri(target, pname); }
|
||||
|
||||
public static void glBufferStorage(int target, long size, int flags) { onBufferStorage(target, flags); RENDER_BACKEND.bufferStorage(target, size, flags); }
|
||||
public static void glBufferStorage(int target, ByteBuffer data, int flags) { onBufferStorage(target, flags); RENDER_BACKEND.bufferStorage(target, data, flags); }
|
||||
public static void glBufferStorage(int target, ShortBuffer data, int flags) { glBufferStorage(target, MemoryUtilities.memByteBuffer(data), flags); }
|
||||
public static void glBufferStorage(int target, IntBuffer data, int flags) { glBufferStorage(target, MemoryUtilities.memByteBuffer(data), flags); }
|
||||
public static void glBufferStorage(int target, FloatBuffer data, int flags) { glBufferStorage(target, MemoryUtilities.memByteBuffer(data), flags); }
|
||||
public static void glBufferStorage(int target, DoubleBuffer data, int flags) { glBufferStorage(target, MemoryUtilities.memByteBuffer(data), flags); }
|
||||
public static void glBufferStorage(int target, short[] data, int flags) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferStorage(target, copy, flags);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferStorage(int target, int[] data, int flags) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferStorage(target, copy, flags);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferStorage(int target, float[] data, int flags) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferStorage(target, copy, flags);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glBufferStorage(int target, double[] data, int flags) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glBufferStorage(target, copy, flags);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
|
||||
public static void glNamedBufferData(int buffer, long size, int usage) { onNamedBufferRespec(ctx(), buffer); RENDER_BACKEND.namedBufferData(buffer, size, usage); }
|
||||
public static void glNamedBufferData(int buffer, ByteBuffer data, int usage) { onNamedBufferRespec(ctx(), buffer); RENDER_BACKEND.namedBufferData(buffer, data, usage); }
|
||||
public static void glNamedBufferData(int buffer, FloatBuffer data, int usage) { onNamedBufferRespec(ctx(), buffer); RENDER_BACKEND.namedBufferData(buffer, data, usage); }
|
||||
public static void glNamedBufferData(int buffer, ShortBuffer data, int usage) { glNamedBufferData(buffer, MemoryUtilities.memByteBuffer(data), usage); }
|
||||
public static void glNamedBufferData(int buffer, IntBuffer data, int usage) { glNamedBufferData(buffer, MemoryUtilities.memByteBuffer(data), usage); }
|
||||
public static void glNamedBufferData(int buffer, LongBuffer data, int usage) { glNamedBufferData(buffer, MemoryUtilities.memByteBuffer(data), usage); }
|
||||
public static void glNamedBufferData(int buffer, DoubleBuffer data, int usage) { glNamedBufferData(buffer, MemoryUtilities.memByteBuffer(data), usage); }
|
||||
public static void glNamedBufferData(int buffer, short[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferData(buffer, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferData(int buffer, int[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferData(buffer, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferData(int buffer, long[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferData(buffer, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferData(int buffer, float[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferData(buffer, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferData(int buffer, double[] data, int usage) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferData(buffer, copy, usage);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
|
||||
public static void glNamedBufferSubData(int buffer, long offset, ByteBuffer data) { onNamedBufferRespec(ctx(), buffer); RENDER_BACKEND.namedBufferSubData(buffer, offset, data); }
|
||||
public static void glNamedBufferSubData(int buffer, long offset, ShortBuffer data) { glNamedBufferSubData(buffer, offset, MemoryUtilities.memByteBuffer(data)); }
|
||||
public static void glNamedBufferSubData(int buffer, long offset, IntBuffer data) { glNamedBufferSubData(buffer, offset, MemoryUtilities.memByteBuffer(data)); }
|
||||
public static void glNamedBufferSubData(int buffer, long offset, LongBuffer data) { glNamedBufferSubData(buffer, offset, MemoryUtilities.memByteBuffer(data)); }
|
||||
public static void glNamedBufferSubData(int buffer, long offset, FloatBuffer data) { glNamedBufferSubData(buffer, offset, MemoryUtilities.memByteBuffer(data)); }
|
||||
public static void glNamedBufferSubData(int buffer, long offset, DoubleBuffer data) { glNamedBufferSubData(buffer, offset, MemoryUtilities.memByteBuffer(data)); }
|
||||
public static void glNamedBufferSubData(int buffer, long offset, short[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferSubData(buffer, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferSubData(int buffer, long offset, int[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferSubData(buffer, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferSubData(int buffer, long offset, long[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferSubData(buffer, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferSubData(int buffer, long offset, float[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferSubData(buffer, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
public static void glNamedBufferSubData(int buffer, long offset, double[] data) {
|
||||
final ByteBuffer copy = copyOf(data);
|
||||
glNamedBufferSubData(buffer, offset, copy);
|
||||
MemoryUtilities.memFree(copy);
|
||||
}
|
||||
|
||||
public static void glClearBufferSubData(int target, int internalFormat, long offset, long size, int format, int type, ByteBuffer data) { onBufferRespec(target); RENDER_BACKEND.clearBufferSubData(target, internalFormat, offset, size, format, type, data); }
|
||||
public static void glClearBufferData(int target, int internalformat, int format, int type, ByteBuffer data) { onBufferRespec(target); RENDER_BACKEND.clearBufferData(target, internalformat, format, type, data); }
|
||||
public static boolean glIsBuffer(int buffer) { rejectExitCapture(); return RENDER_BACKEND.isBuffer(buffer); }
|
||||
public static void glCopyBufferSubData(int readTarget, int writeTarget, long readOffset, long writeOffset, long size) { onBufferRespec(writeTarget); RENDER_BACKEND.copyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size); }
|
||||
|
||||
private static int checkedSize(long size) {
|
||||
if (size < 0 || size > Integer.MAX_VALUE) {
|
||||
throw new IllegalArgumentException("Buffer range does not fit a ByteBuffer wrapper: " + size);
|
||||
}
|
||||
return (int) size;
|
||||
}
|
||||
|
||||
private static ByteBuffer copyOf(short[] data) {
|
||||
final ByteBuffer bb = MemoryUtilities.memAlloc(data.length << 1);
|
||||
bb.asShortBuffer().put(data);
|
||||
return bb;
|
||||
}
|
||||
|
||||
private static ByteBuffer copyOf(int[] data) {
|
||||
final ByteBuffer bb = MemoryUtilities.memAlloc(data.length << 2);
|
||||
bb.asIntBuffer().put(data);
|
||||
return bb;
|
||||
}
|
||||
|
||||
private static ByteBuffer copyOf(long[] data) {
|
||||
final ByteBuffer bb = MemoryUtilities.memAlloc(data.length << 3);
|
||||
bb.asLongBuffer().put(data);
|
||||
return bb;
|
||||
}
|
||||
|
||||
private static ByteBuffer copyOf(float[] data) {
|
||||
final ByteBuffer bb = MemoryUtilities.memAlloc(data.length << 2);
|
||||
bb.asFloatBuffer().put(data);
|
||||
return bb;
|
||||
}
|
||||
|
||||
private static ByteBuffer copyOf(double[] data) {
|
||||
final ByteBuffer bb = MemoryUtilities.memAlloc(data.length << 3);
|
||||
bb.asDoubleBuffer().put(data);
|
||||
return bb;
|
||||
}
|
||||
|
||||
public static void glBindBufferBase(int target, int index, int buffer) {
|
||||
rejectExitCapture();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
final GLContextState glCtx = ctx();
|
||||
trackBufferBinding(glCtx, target, buffer);
|
||||
trackIndexedBufferBinding(glCtx, target, index, buffer);
|
||||
RENDER_BACKEND.bindBufferBase(target, index, buffer);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glBindBufferRange(int target, int index, int buffer, long offset, long size) {
|
||||
rejectExitCapture();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
final GLContextState glCtx = ctx();
|
||||
trackBufferBinding(glCtx, target, buffer);
|
||||
trackIndexedBufferBinding(glCtx, target, index, buffer);
|
||||
RENDER_BACKEND.bindBufferRange(target, index, buffer, offset, size);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static int[] indexedBufferBindings(GLContextState glCtx, int target, int index) {
|
||||
if (index < 0 || index >= INDEXED_BUFFER_SLOTS) return null;
|
||||
if (target == GL31.GL_UNIFORM_BUFFER) return glCtx.uniformBufferBindings;
|
||||
if (target == GL43.GL_SHADER_STORAGE_BUFFER) return glCtx.storageBufferBindings;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void trackIndexedBufferBinding(GLContextState glCtx, int target, int index, int buffer) {
|
||||
final int[] bindings = indexedBufferBindings(glCtx, target, index);
|
||||
if (bindings != null) bindings[index] = buffer;
|
||||
}
|
||||
|
||||
public static int getIndexedBufferBinding(int target, int index) {
|
||||
if (isCachingEnabled()) {
|
||||
final int[] bindings = indexedBufferBindings(ctx(), target, index);
|
||||
if (bindings != null) return bindings[index];
|
||||
}
|
||||
return RENDER_BACKEND.getIndexedBufferBinding(target, index);
|
||||
}
|
||||
public static long nglMapBuffer(int target, int access) {
|
||||
rejectExitCapture();
|
||||
final ByteBuffer buf = RENDER_BACKEND.mapBuffer(target, access);
|
||||
if (buf != null) onBufferMap(target, access);
|
||||
return buf == null ? 0L : MemoryUtilities.memAddress0(buf);
|
||||
}
|
||||
|
||||
public static void glMemoryBarrier(int barriers) { rejectExitCapture(); RENDER_BACKEND.memoryBarrier(barriers); }
|
||||
|
||||
public static int getBoundVBO() {
|
||||
return ctx().boundVBO;
|
||||
}
|
||||
|
||||
public static int getBoundCopyReadBuffer() {
|
||||
return ctx().boundCopyReadBuffer;
|
||||
}
|
||||
|
||||
public static int getBoundCopyWriteBuffer() {
|
||||
return ctx().boundCopyWriteBuffer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,524 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.InstancedAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GlintColorHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.ImmediateExtendedAttribHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.Color4Stack;
|
||||
import com.gtnewhorizons.angelica.glsm.streaming.TessellatorEntityIds;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isMainThread;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMCurrentAttribs {
|
||||
|
||||
private GLSMCurrentAttribs() {}
|
||||
|
||||
public static void setOverlayColor(float r, float g, float b, float a) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.OVERLAY_COLOR);
|
||||
if (r == glCtx.overlayR && g == glCtx.overlayG && b == glCtx.overlayB && a == glCtx.overlayA) return;
|
||||
glCtx.overlayR = r; glCtx.overlayG = g; glCtx.overlayB = b; glCtx.overlayA = a;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
|
||||
public static void setShaderColor(float r, float g, float b, float a) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.SHADER_COLOR);
|
||||
if (r == glCtx.shaderColorR && g == glCtx.shaderColorG && b == glCtx.shaderColorB && a == glCtx.shaderColorA) return;
|
||||
glCtx.shaderColorR = r; glCtx.shaderColorG = g; glCtx.shaderColorB = b; glCtx.shaderColorA = a;
|
||||
if (GLSMHooks.SHADER_COLOR_CHANGE.hasListeners()) {
|
||||
GLSMHooks.shaderColorChangeEvent.red = r;
|
||||
GLSMHooks.shaderColorChangeEvent.green = g;
|
||||
GLSMHooks.shaderColorChangeEvent.blue = b;
|
||||
GLSMHooks.shaderColorChangeEvent.alpha = a;
|
||||
GLSMHooks.SHADER_COLOR_CHANGE.post(GLSMHooks.shaderColorChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean consumeUnit23TexCoordSetDuringDraw(GLContextState glCtx) {
|
||||
boolean v = glCtx.unit23TexCoordSetDuringDraw;
|
||||
glCtx.unit23TexCoordSetDuringDraw = false;
|
||||
return v;
|
||||
}
|
||||
|
||||
public static void forceAttribDefaultsDirty() {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
// has* bits mark attribs the VBO already supplies; FFP supplies the rest via u_Current* uniforms.
|
||||
// Skip the backend vertexAttrib call in either case
|
||||
public static void flushDeferredVertexAttribs(GLContextState glCtx, boolean hasColor, boolean hasNormal, boolean hasTexCoord, boolean hasLightmap) {
|
||||
final ShaderManager sm = glCtx.ffp;
|
||||
final boolean ffpWillHandle = sm.isActive() || (sm.isEnabled() && glCtx.activeProgram == 0);
|
||||
if (!hasColor && glCtx.dirtyColorAttrib && !ffpWillHandle) {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.COLOR.getAttributeLocation(), glCtx.color.getRed(), glCtx.color.getGreen(), glCtx.color.getBlue(), glCtx.color.getAlpha());
|
||||
glCtx.dirtyColorAttrib = false;
|
||||
}
|
||||
if (!hasNormal && glCtx.dirtyNormalAttrib && !ffpWillHandle) {
|
||||
final var n = sm.currentNormal;
|
||||
RENDER_BACKEND.vertexAttrib3f(Usage.NORMAL.getAttributeLocation(), n.x, n.y, n.z);
|
||||
glCtx.dirtyNormalAttrib = false;
|
||||
}
|
||||
if (!hasTexCoord && glCtx.dirtyTexCoordAttrib && !ffpWillHandle) {
|
||||
final var tc = sm.currentTexCoords[0];
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.PRIMARY_UV.getAttributeLocation(), tc.x, tc.y, tc.z, tc.w);
|
||||
glCtx.dirtyTexCoordAttrib = false;
|
||||
}
|
||||
if (!hasLightmap && glCtx.dirtyLightmapAttrib && !ffpWillHandle) {
|
||||
RENDER_BACKEND.vertexAttrib4f(Usage.SECONDARY_UV.getAttributeLocation(), glCtx.lastBrightnessX, glCtx.lastBrightnessY, 0.0f, 1.0f);
|
||||
glCtx.dirtyLightmapAttrib = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setEntityIds(int entity, int blockEntity, int item) {
|
||||
rejectExitCapture();
|
||||
if (!isMainThread()) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
final long ids = InstancedAttribs.packEntityInfo(entity, blockEntity, item);
|
||||
if (ids == glCtx.entityIds) return;
|
||||
TessellatorEntityIds.onIdsChanged(glCtx.entityIds, ids);
|
||||
glCtx.entityIds = ids;
|
||||
glCtx.dirtyEntityIdsAttrib = true;
|
||||
}
|
||||
|
||||
public static void flushEntityIds(GLContextState glCtx) {
|
||||
if (!glCtx.dirtyEntityIdsAttrib || glCtx.activeProgram == 0) return;
|
||||
final ImmediateExtendedAttribHandler handler = GLSMHooks.immediateExtendedHandler;
|
||||
if (handler == null || !handler.wantsEntityIds()) return;
|
||||
final long ids = glCtx.entityIds;
|
||||
RENDER_BACKEND.vertexAttrib4f(ImmediateExtendedAttribHandler.LOC_ENTITY_IDS,
|
||||
InstancedAttribs.normalizedId(ids, 0), InstancedAttribs.normalizedId(ids, 16), InstancedAttribs.normalizedId(ids, 32), 0.0f);
|
||||
glCtx.dirtyEntityIdsAttrib = false;
|
||||
}
|
||||
|
||||
public static void glNormal3b(byte nx, byte ny, byte nz) {
|
||||
final float fnx = b2f(nx), fny = b2f(ny), fnz = b2f(nz);
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setNormal(fnx, fny, fnz);
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setNormal(fnx, fny, fnz);
|
||||
return;
|
||||
}
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
}
|
||||
|
||||
public static void glNormal3d(double nx, double ny, double nz) {
|
||||
final float fnx = (float) nx, fny = (float) ny, fnz = (float) nz;
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setNormal(fnx, fny, fnz);
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setNormal(fnx, fny, fnz);
|
||||
return;
|
||||
}
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
}
|
||||
|
||||
public static void glNormal3f(float nx, float ny, float nz) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setNormal(nx, ny, nz);
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setNormal(nx, ny, nz);
|
||||
return;
|
||||
}
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
}
|
||||
|
||||
public static void glNormal3i(int nx, int ny, int nz) {
|
||||
final float fnx = nx / 2147483647.0f, fny = ny / 2147483647.0f, fnz = nz / 2147483647.0f;
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setNormal(fnx, fny, fnz);
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setNormal(fnx, fny, fnz);
|
||||
return;
|
||||
}
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
}
|
||||
|
||||
public static void glEdgeFlag(boolean flag) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStateCommand(() -> glEdgeFlag(flag));
|
||||
if (mode == RecordMode.COMPILE) return;
|
||||
}
|
||||
ctx().edgeFlagState.setEnabled(flag);
|
||||
}
|
||||
|
||||
public static void glColor4f(float red, float green, float blue, float alpha) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor(red, green, blue, alpha);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor(red, green, blue, alpha);
|
||||
}
|
||||
|
||||
public static void glColor4d(double red, double green, double blue, double alpha) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor((float) red, (float) green, (float) blue, (float) alpha);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor((float) red, (float) green, (float) blue, (float) alpha);
|
||||
}
|
||||
|
||||
public static void glColor4b(byte red, byte green, byte blue, byte alpha) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor(b2f(red), b2f(green), b2f(blue), b2f(alpha));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor(b2f(red), b2f(green), b2f(blue), b2f(alpha));
|
||||
}
|
||||
|
||||
public static void glColor4ub(byte red, byte green, byte blue, byte alpha) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor(ub2f(red), ub2f(green), ub2f(blue), ub2f(alpha));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor(ub2f(red), ub2f(green), ub2f(blue), ub2f(alpha));
|
||||
}
|
||||
|
||||
public static void glColor3f(float red, float green, float blue) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor(red, green, blue, 1.0F);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor(red, green, blue, 1.0F);
|
||||
}
|
||||
|
||||
public static void glColor3d(double red, double green, double blue) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor((float) red, (float) green, (float) blue, 1.0F);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor((float) red, (float) green, (float) blue, 1.0F);
|
||||
}
|
||||
|
||||
public static void glColor3b(byte red, byte green, byte blue) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor(b2f(red), b2f(green), b2f(blue), 1.0F);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor(b2f(red), b2f(green), b2f(blue), 1.0F);
|
||||
}
|
||||
|
||||
public static void glColor3ub(byte red, byte green, byte blue) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColor(ub2f(red), ub2f(green), ub2f(blue), 1.0F);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeColor(ub2f(red), ub2f(green), ub2f(blue), 1.0F);
|
||||
}
|
||||
|
||||
private static float ub2f(byte b) {
|
||||
return (b & 0xFF) / 255.0F;
|
||||
}
|
||||
|
||||
private static float b2f(byte b) {
|
||||
return ((b - Byte.MIN_VALUE) & 0xFF) / 255.0F;
|
||||
}
|
||||
|
||||
private static boolean changeColor(float red, float green, float blue, float alpha) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.COLOR);
|
||||
// Helper function for glColor*
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || red != glCtx.color.getRed() || green != glCtx.color.getGreen() || blue != glCtx.color.getBlue() || alpha != glCtx.color.getAlpha()) {
|
||||
mod(glCtx.color);
|
||||
glCtx.color.setRed(red);
|
||||
glCtx.color.setGreen(green);
|
||||
glCtx.color.setBlue(blue);
|
||||
glCtx.color.setAlpha(alpha);
|
||||
glCtx.colorGeneration++;
|
||||
if (ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setColor(red, green, blue, alpha);
|
||||
}
|
||||
glCtx.dirtyColorAttrib = true;
|
||||
// Only set while an enchantment-glint span is active
|
||||
final GlintColorHandler glintHandler = GLSMHooks.glintColorHandler;
|
||||
if (glintHandler != null) {
|
||||
glintHandler.onColorChanged(red, green, blue, alpha);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void glSecondaryColor3f(float red, float green, float blue) {
|
||||
rejectExitCapture();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordSecondaryColor(red, green, blue);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
changeSecondaryColor(red, green, blue);
|
||||
}
|
||||
|
||||
public static void glSecondaryColor3d(double red, double green, double blue) {
|
||||
glSecondaryColor3f((float) red, (float) green, (float) blue);
|
||||
}
|
||||
|
||||
public static void glSecondaryColor3b(byte red, byte green, byte blue) {
|
||||
glSecondaryColor3f(b2f(red), b2f(green), b2f(blue));
|
||||
}
|
||||
|
||||
public static void glSecondaryColor3ub(byte red, byte green, byte blue) {
|
||||
glSecondaryColor3f(ub2f(red), ub2f(green), ub2f(blue));
|
||||
}
|
||||
|
||||
/** Helper for glSecondaryColor* - the color sum is emulated by the FFP shaders, nothing is sent to the driver. */
|
||||
private static void changeSecondaryColor(float red, float green, float blue) {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled() || red != glCtx.secondaryColor.getRed() || green != glCtx.secondaryColor.getGreen() || blue != glCtx.secondaryColor.getBlue()) {
|
||||
if (glCtx.colorSumState.isEnabled()) beforeUncapturedStateChange();
|
||||
mod(glCtx.secondaryColor);
|
||||
glCtx.secondaryColor.setRed(red);
|
||||
glCtx.secondaryColor.setGreen(green);
|
||||
glCtx.secondaryColor.setBlue(blue);
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glTexCoord1f(float s) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord(s, 0.0f);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord(s, 0.0f, 0.0f, 1.0f);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glTexCoord1d(double s) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord((float) s, 0.0f);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord((float) s, 0.0f, 0.0f, 1.0f);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glTexCoord2f(float s, float t) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord(s, t);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord(s, t, 0.0f, 1.0f);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glTexCoord2d(double s, double t) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord((float) s, (float) t);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord((float) s, (float) t, 0.0f, 1.0f);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glTexCoord3f(float s, float t, float r) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord(s, t); // Only track s,t for 2D textures
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord(s, t, r, 1.0f);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glTexCoord3d(double s, double t, double r) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord((float) s, (float) t);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord((float) s, (float) t, (float) r, 1.0f);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glTexCoord4f(float s, float t, float r, float q) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord(s, t);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord(s, t, r, q);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glTexCoord4d(double s, double t, double r, double q) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord((float) s, (float) t);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.ffp.setTexCoord((float) s, (float) t, (float) r, (float) q);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
}
|
||||
|
||||
public static void glVertexAttrib2f(int index, float v0, float v1) {
|
||||
glVertexAttrib4f(index, v0, v1, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
public static void glVertexAttrib2s(int index, short v0, short v1) {
|
||||
glVertexAttrib4f(index, v0, v1, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
public static void glVertexAttrib3f(int index, float v0, float v1, float v2) {
|
||||
glVertexAttrib4f(index, v0, v1, v2, 1.0f);
|
||||
}
|
||||
|
||||
public static void glVertexAttrib4f(int index, float v0, float v1, float v2, float v3) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordVertexAttrib(index, v0, v1, v2, v3);
|
||||
if (mode == RecordMode.COMPILE) return;
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
RENDER_BACKEND.vertexAttrib4f(index, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
public static void glMultiTexCoord2f(int target, float s, float t) {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (target == GL13.GL_TEXTURE0) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setTexCoord(s, t);
|
||||
return;
|
||||
}
|
||||
glCtx.ffp.setTexCoord(s, t, 0.0f, 1.0f);
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
} else if (target == GL13.GL_TEXTURE1) {
|
||||
if (ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.setLightmapCoord(s, t);
|
||||
return;
|
||||
}
|
||||
setLightmapTextureCoords(target, s, t);
|
||||
} else {
|
||||
final int unit = target - GL13.GL_TEXTURE0;
|
||||
if (unit >= 2 && unit < 4) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
glCtx.unit23TexCoordSetDuringDraw = true;
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
glCtx.ffp.setTexCoord(unit, s, t, 0.0f, 1.0f);
|
||||
} else {
|
||||
glCtx.exitCapture.reject();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glMultiTexCoord2d(int target, double s, double t) {
|
||||
glMultiTexCoord2f(target, (float) s, (float) t);
|
||||
}
|
||||
|
||||
public static void glMultiTexCoord2s(int target, short s, short t) {
|
||||
glMultiTexCoord2f(target, s, t);
|
||||
}
|
||||
|
||||
public static void setLightmapTextureCoords(int unit, float x, float y) {
|
||||
if (unit != GL13.GL_TEXTURE1) {
|
||||
rejectExitCapture();
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.LIGHTMAP);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStateCommand(() -> setLightmapTextureCoords(unit, x, y));
|
||||
if (mode == RecordMode.COMPILE) return;
|
||||
}
|
||||
glCtx.lastBrightnessX = x;
|
||||
glCtx.lastBrightnessY = y;
|
||||
glCtx.dirtyLightmapAttrib = true;
|
||||
if (GLSMHooks.LIGHTMAP_COORDS.hasListeners()) {
|
||||
GLSMHooks.lightmapCoordsEvent.x = x;
|
||||
GLSMHooks.lightmapCoordsEvent.y = y;
|
||||
GLSMHooks.LIGHTMAP_COORDS.post(GLSMHooks.lightmapCoordsEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public static float getOverlayR() {
|
||||
return ctx().overlayR;
|
||||
}
|
||||
|
||||
public static float getOverlayG() {
|
||||
return ctx().overlayG;
|
||||
}
|
||||
|
||||
public static float getOverlayB() {
|
||||
return ctx().overlayB;
|
||||
}
|
||||
|
||||
public static float getOverlayA() {
|
||||
return ctx().overlayA;
|
||||
}
|
||||
|
||||
public static float getShaderColorR() {
|
||||
return ctx().shaderColorR;
|
||||
}
|
||||
|
||||
public static float getShaderColorG() {
|
||||
return ctx().shaderColorG;
|
||||
}
|
||||
|
||||
public static float getShaderColorB() {
|
||||
return ctx().shaderColorB;
|
||||
}
|
||||
|
||||
public static float getShaderColorA() {
|
||||
return ctx().shaderColorA;
|
||||
}
|
||||
|
||||
public static Color4Stack getColor() {
|
||||
return ctx().color;
|
||||
}
|
||||
|
||||
public static Color4Stack getSecondaryColor() {
|
||||
return ctx().secondaryColor;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getColorSumState() {
|
||||
return ctx().colorSumState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,427 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredAlphaHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredDepthColorHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.AlphaStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.DepthStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.StencilStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.AlphaState;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMDepthStencilAlpha {
|
||||
|
||||
private GLSMDepthStencilAlpha() {}
|
||||
|
||||
public static boolean isEffectiveDepthMaskEnabled() {
|
||||
return ctx().depthState.isEffectiveMaskEnabled();
|
||||
}
|
||||
|
||||
public static boolean isEffectiveAlphaTestEnabled() {
|
||||
return ctx().alphaTest.isEffectivelyEnabled();
|
||||
}
|
||||
|
||||
public static AlphaState getEffectiveAlphaState(AlphaState out) {
|
||||
return ctx().alphaState.readEffective(out);
|
||||
}
|
||||
|
||||
public static void glDepthFunc(int func) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.DEPTH_FUNC);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDepthFunc(func);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || func != glCtx.depthState.getFunc()) {
|
||||
mod(glCtx.depthState);
|
||||
glCtx.depthState.setFunc(func);
|
||||
RENDER_BACKEND.depthFunc(func);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDepthMask(boolean mask) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.writeDepthColor(ExitStateCapture.DEPTH_MASK);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDepthMask(mask);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final DeferredDepthColorHandler dch = GLSMHooks.depthColorHandler;
|
||||
if (dch != null && dch.isDepthColorLocked()) {
|
||||
mod(glCtx.depthState);
|
||||
dch.deferDepthEnable(mask);
|
||||
return;
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || mask != glCtx.depthState.isEnabled()) {
|
||||
mod(glCtx.depthState);
|
||||
glCtx.depthState.setEnabled(mask);
|
||||
RENDER_BACKEND.depthMask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glClearDepth(double depth) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordClearDepth(depth);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
depth = Math.min(1.0, Math.max(0.0, depth));
|
||||
mod(glCtx.depthState);
|
||||
if (isCachingEnabled()) glCtx.depthState.setClearValue(depth);
|
||||
RENDER_BACKEND.clearDepth(depth);
|
||||
}
|
||||
|
||||
public static void enableAlphaTest() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_ALPHA_TEST);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableAlphaTest(ctx());
|
||||
}
|
||||
|
||||
static void enableAlphaTest(GLContextState glCtx) {
|
||||
final DeferredAlphaHandler ah = GLSMHooks.alphaHandler;
|
||||
if (ah != null && ah.isAlphaTestLocked()) {
|
||||
glCtx.exitCapture.capability(GL11.GL_ALPHA_TEST, -1);
|
||||
glCtx.alphaTest.beforeModify();
|
||||
if (ah.deferAlphaTestToggle(true) && GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
final boolean wasEnabled = glCtx.alphaTest.isEnabled();
|
||||
glCtx.alphaTest.enable();
|
||||
if (glCtx.alphaTest.isEnabled() != wasEnabled) {
|
||||
glCtx.fragmentGeneration++;
|
||||
if (GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void disableAlphaTest() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_ALPHA_TEST);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableAlphaTest(ctx());
|
||||
}
|
||||
|
||||
static void disableAlphaTest(GLContextState glCtx) {
|
||||
final DeferredAlphaHandler ah = GLSMHooks.alphaHandler;
|
||||
if (ah != null && ah.isAlphaTestLocked()) {
|
||||
glCtx.exitCapture.capability(GL11.GL_ALPHA_TEST, -1);
|
||||
glCtx.alphaTest.beforeModify();
|
||||
if (ah.deferAlphaTestToggle(false) && GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
final boolean wasEnabled = glCtx.alphaTest.isEnabled();
|
||||
glCtx.alphaTest.disable();
|
||||
if (glCtx.alphaTest.isEnabled() != wasEnabled) {
|
||||
glCtx.fragmentGeneration++;
|
||||
if (GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glAlphaFunc(int function, float reference) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.writeAlpha();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordAlphaFunc(function, reference);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final DeferredAlphaHandler ah = GLSMHooks.alphaHandler;
|
||||
if (ah != null && ah.isAlphaTestLocked()) {
|
||||
mod(glCtx.alphaState);
|
||||
if (ah.deferAlphaFunc(function, reference) && GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()
|
||||
&& (function != glCtx.alphaState.getFunction() || Float.compare(reference, glCtx.alphaState.getReference()) != 0)) {
|
||||
mod(glCtx.alphaState);
|
||||
glCtx.alphaState.setFunction(function);
|
||||
glCtx.alphaState.setReference(reference);
|
||||
glCtx.fragmentGeneration++;
|
||||
if (GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void enableDepthTest() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_DEPTH_TEST);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableDepthTest(ctx());
|
||||
}
|
||||
|
||||
static void enableDepthTest(GLContextState glCtx) {
|
||||
glCtx.depthTest.enable();
|
||||
}
|
||||
|
||||
public static void disableDepthTest() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_DEPTH_TEST);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableDepthTest(ctx());
|
||||
}
|
||||
|
||||
static void disableDepthTest(GLContextState glCtx) {
|
||||
glCtx.depthTest.disable();
|
||||
}
|
||||
|
||||
public static void glDepthRange(double near, double far) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled() || glCtx.viewportState.depthRangeNear != near || glCtx.viewportState.depthRangeFar != far) beforeUncapturedStateChange();
|
||||
if (isCachingEnabled()) mod(glCtx.viewportState).setDepthRange(near, far);
|
||||
RENDER_BACKEND.depthRange(near, far);
|
||||
}
|
||||
|
||||
public static void glStencilFunc(int func, int ref, int mask) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStencilFunc(func, ref, mask);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final int clampedMask = mask & glCtx.stencilBitMask;
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.stencilState.getFuncFront() != func || glCtx.stencilState.getRefFront() != ref || glCtx.stencilState.getValueMaskFront() != clampedMask) {
|
||||
beforeUncapturedStateChange();
|
||||
mod(glCtx.stencilState).setFunc(func, ref, clampedMask);
|
||||
RENDER_BACKEND.stencilFunc(func, ref, clampedMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glStencilMask(int mask) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStencilMask(mask);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final int clampedMask = mask & glCtx.stencilBitMask;
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.stencilState.getWriteMaskFront() != clampedMask) {
|
||||
beforeUncapturedStateChange();
|
||||
mod(glCtx.stencilState).setWriteMask(clampedMask);
|
||||
RENDER_BACKEND.stencilMask(clampedMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glStencilOp(int fail, int zfail, int zpass) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStencilOp(fail, zfail, zpass);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.stencilState.getFailOpFront() != fail || glCtx.stencilState.getZFailOpFront() != zfail || glCtx.stencilState.getZPassOpFront() != zpass) {
|
||||
beforeUncapturedStateChange();
|
||||
mod(glCtx.stencilState).setOp(fail, zfail, zpass);
|
||||
RENDER_BACKEND.stencilOp(fail, zfail, zpass);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glClearStencil(int s) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordClearStencil(s);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.stencilState.getClearValue() != s) {
|
||||
mod(glCtx.stencilState).setClearValue(s);
|
||||
RENDER_BACKEND.clearStencil(s);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glStencilFuncSeparate(int face, int func, int ref, int mask) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStencilFuncSeparate(face, func, ref, mask);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
final int clampedMask = mask & glCtx.stencilBitMask;
|
||||
final boolean caching = isCachingEnabled();
|
||||
boolean needsUpdate = !caching;
|
||||
if (!needsUpdate) {
|
||||
if (face == GL11.GL_FRONT || face == GL11.GL_FRONT_AND_BACK) {
|
||||
needsUpdate = glCtx.stencilState.getFuncFront() != func || glCtx.stencilState.getRefFront() != ref || glCtx.stencilState.getValueMaskFront() != clampedMask;
|
||||
}
|
||||
if (!needsUpdate && (face == GL11.GL_BACK || face == GL11.GL_FRONT_AND_BACK)) {
|
||||
needsUpdate = glCtx.stencilState.getFuncBack() != func || glCtx.stencilState.getRefBack() != ref || glCtx.stencilState.getValueMaskBack() != clampedMask;
|
||||
}
|
||||
}
|
||||
if (needsUpdate) {
|
||||
mod(glCtx.stencilState);
|
||||
if (face == GL11.GL_FRONT || face == GL11.GL_FRONT_AND_BACK) {
|
||||
glCtx.stencilState.setFuncFront(func);
|
||||
glCtx.stencilState.setRefFront(ref);
|
||||
glCtx.stencilState.setValueMaskFront(clampedMask);
|
||||
}
|
||||
if (face == GL11.GL_BACK || face == GL11.GL_FRONT_AND_BACK) {
|
||||
glCtx.stencilState.setFuncBack(func);
|
||||
glCtx.stencilState.setRefBack(ref);
|
||||
glCtx.stencilState.setValueMaskBack(clampedMask);
|
||||
}
|
||||
RENDER_BACKEND.stencilFuncSeparate(face, func, ref, clampedMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glStencilMaskSeparate(int face, int mask) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStencilMaskSeparate(face, mask);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
final int clampedMask = mask & glCtx.stencilBitMask;
|
||||
final boolean caching = isCachingEnabled();
|
||||
boolean needsUpdate = !caching;
|
||||
if (!needsUpdate) {
|
||||
if (face == GL11.GL_FRONT || face == GL11.GL_FRONT_AND_BACK) {
|
||||
needsUpdate = glCtx.stencilState.getWriteMaskFront() != clampedMask;
|
||||
}
|
||||
if (!needsUpdate && (face == GL11.GL_BACK || face == GL11.GL_FRONT_AND_BACK)) {
|
||||
needsUpdate = glCtx.stencilState.getWriteMaskBack() != clampedMask;
|
||||
}
|
||||
}
|
||||
if (needsUpdate) {
|
||||
mod(glCtx.stencilState);
|
||||
if (face == GL11.GL_FRONT || face == GL11.GL_FRONT_AND_BACK) {
|
||||
glCtx.stencilState.setWriteMaskFront(clampedMask);
|
||||
}
|
||||
if (face == GL11.GL_BACK || face == GL11.GL_FRONT_AND_BACK) {
|
||||
glCtx.stencilState.setWriteMaskBack(clampedMask);
|
||||
}
|
||||
RENDER_BACKEND.stencilMaskSeparate(face, clampedMask);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glStencilOpSeparate(int face, int sfail, int dpfail, int dppass) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordStencilOpSeparate(face, sfail, dpfail, dppass);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
final boolean caching = isCachingEnabled();
|
||||
boolean needsUpdate = !caching;
|
||||
if (!needsUpdate) {
|
||||
if (face == GL11.GL_FRONT || face == GL11.GL_FRONT_AND_BACK) {
|
||||
needsUpdate = glCtx.stencilState.getFailOpFront() != sfail || glCtx.stencilState.getZFailOpFront() != dpfail || glCtx.stencilState.getZPassOpFront() != dppass;
|
||||
}
|
||||
if (!needsUpdate && (face == GL11.GL_BACK || face == GL11.GL_FRONT_AND_BACK)) {
|
||||
needsUpdate = glCtx.stencilState.getFailOpBack() != sfail || glCtx.stencilState.getZFailOpBack() != dpfail || glCtx.stencilState.getZPassOpBack() != dppass;
|
||||
}
|
||||
}
|
||||
if (needsUpdate) {
|
||||
mod(glCtx.stencilState);
|
||||
if (face == GL11.GL_FRONT || face == GL11.GL_FRONT_AND_BACK) {
|
||||
glCtx.stencilState.setFailOpFront(sfail);
|
||||
glCtx.stencilState.setZFailOpFront(dpfail);
|
||||
glCtx.stencilState.setZPassOpFront(dppass);
|
||||
}
|
||||
if (face == GL11.GL_BACK || face == GL11.GL_FRONT_AND_BACK) {
|
||||
glCtx.stencilState.setFailOpBack(sfail);
|
||||
glCtx.stencilState.setZFailOpBack(dpfail);
|
||||
glCtx.stencilState.setZPassOpBack(dppass);
|
||||
}
|
||||
RENDER_BACKEND.stencilOpSeparate(face, sfail, dpfail, dppass);
|
||||
}
|
||||
}
|
||||
|
||||
public static DepthStateStack getDepthState() {
|
||||
return ctx().depthState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getDepthTest() {
|
||||
return ctx().depthTest;
|
||||
}
|
||||
|
||||
public static AlphaStateStack getAlphaState() {
|
||||
return ctx().alphaState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getAlphaTest() {
|
||||
return ctx().alphaTest;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getStencilTest() {
|
||||
return ctx().stencilTest;
|
||||
}
|
||||
|
||||
public static StencilStateStack getStencilState() {
|
||||
return ctx().stencilState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,713 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.GLDebugMessageListener;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.FfpExtendedAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CommandRecorder;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CompiledDisplayList;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.commands.IndexedDrawCapture;
|
||||
import com.gtnewhorizons.angelica.glsm.streaming.LineQuads;
|
||||
import com.gtnewhorizons.angelica.glsm.streaming.TessellatorStreamingDrawer;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.KHRDebugCallback;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.LOGGER;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.acquireDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.guardUnsupportedFFP;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.initConfig;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.releaseDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.warnOnce;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMDraws {
|
||||
|
||||
private GLSMDraws() {}
|
||||
|
||||
public static long drawCalls;
|
||||
|
||||
/**
|
||||
* Check if a display list exists (has been compiled and stored). Delegates to DisplayListManager.
|
||||
*
|
||||
* @param list The display list ID to check
|
||||
* @return true if the display list exists, false otherwise
|
||||
*/
|
||||
public static boolean displayListExists(int list) {
|
||||
return DisplayListManager.displayListExists(list);
|
||||
}
|
||||
|
||||
private static final String PIXELTRANSFER_MSG = "glPixelTransfer is not available in GL 3.3 core profile.";
|
||||
|
||||
public static void glPixelTransferf(int pname, float param) {
|
||||
guardUnsupportedFFP("glPixelTransfer", PIXELTRANSFER_MSG);
|
||||
}
|
||||
|
||||
public static void glPixelTransferi(int pname, int param) {
|
||||
guardUnsupportedFFP("glPixelTransfer", PIXELTRANSFER_MSG);
|
||||
}
|
||||
|
||||
private static final String RASTERPOS_MSG = "glRasterPos is not available in GL 3.3 core profile.";
|
||||
|
||||
public static void glRasterPos2f(float x, float y) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos2d(double x, double y) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos2i(int x, int y) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos3f(float x, float y, float z) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos3d(double x, double y, double z) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos3i(int x, int y, int z) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos4f(float x, float y, float z, float w) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos4d(double x, double y, double z, double w) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
public static void glRasterPos4i(int x, int y, int z, int w) { guardUnsupportedFFP("glRasterPos", RASTERPOS_MSG); }
|
||||
|
||||
public static void glBegin(int mode) {
|
||||
rejectExitCapture();
|
||||
ctx().unit23TexCoordSetDuringDraw = false;
|
||||
if (DisplayListManager.isRecording()) {
|
||||
ImmediateModeRecorder.begin(mode);
|
||||
return;
|
||||
}
|
||||
ImmediateModeRecorder.beginLive(mode);
|
||||
}
|
||||
|
||||
public static void glEnd() {
|
||||
rejectExitCapture();
|
||||
final DirectTessellator result = ImmediateModeRecorder.end();
|
||||
if (result != null) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
if (DisplayListManager.isCompileAndExecute() && initConfig != null && initConfig.getDirectDrawer() != null) {
|
||||
final CommandRecorder recorder = DisplayListManager.pauseRecording();
|
||||
initConfig.getDirectDrawer().accept(result);
|
||||
DisplayListManager.resumeRecording(recorder);
|
||||
}
|
||||
DisplayListManager.addImmediateModeDraw(result);
|
||||
return;
|
||||
}
|
||||
if (initConfig != null && initConfig.getDirectDrawer() != null) {
|
||||
initConfig.getDirectDrawer().accept(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertex2f(float x, float y) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.vertex(x, y, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertex2i(int x, int y) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.vertex((float) x, (float) y, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertex2d(double x, double y) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.vertex((float) x, (float) y, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertex3f(float x, float y, float z) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.vertex(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertex3d(double x, double y, double z) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.vertex((float) x, (float) y, (float) z);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertex3i(int x, int y, int z) {
|
||||
if (DisplayListManager.isRecording() || ImmediateModeRecorder.isDrawing()) {
|
||||
ImmediateModeRecorder.vertex((float) x, (float) y, (float) z);
|
||||
}
|
||||
}
|
||||
|
||||
public static void preDraw(GLContextState glCtx, int drawMode) {
|
||||
prepareLineEmulation(glCtx, drawMode);
|
||||
glCtx.ffp.preDraw(glCtx);
|
||||
GLSMVertexInput.prepareClientArrays(glCtx);
|
||||
}
|
||||
|
||||
public static void glDrawElements(int mode, ByteBuffer indices) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
CommandRecorder savedRecorder = null;
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
final IndexedDrawCapture capture = IndexedDrawCapture.createFromClientIndices(mode, indices.remaining(), GL11.GL_UNSIGNED_BYTE, MemoryUtilities.memAddress(indices), indices.remaining());
|
||||
if (capture != null) DisplayListManager.recordIndexedDrawCapture(capture);
|
||||
if (recordMode == RecordMode.COMPILE) return;
|
||||
savedRecorder = DisplayListManager.pauseRecording();
|
||||
} else if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, indices);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(glCtx, indices.remaining(), GL11.GL_UNSIGNED_BYTE, indices);
|
||||
return;
|
||||
}
|
||||
if (widensLineDraw(mode, indices.remaining())) {
|
||||
drawLinesAsQuads(glCtx, ImmediateModeRecorder.processDrawElementsFromAttribs(mode, indices.remaining(), GL11.GL_UNSIGNED_BYTE, MemoryUtilities.memAddress(indices)));
|
||||
return;
|
||||
}
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawElements(mode, indices);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDrawElements(int mode, IntBuffer indices) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
CommandRecorder savedRecorder = null;
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
final IndexedDrawCapture capture = IndexedDrawCapture.createFromClientIndices(mode, indices.remaining(), GL11.GL_UNSIGNED_INT, MemoryUtilities.memAddress(indices), (long) indices.remaining() << 2);
|
||||
if (capture != null) DisplayListManager.recordIndexedDrawCapture(capture);
|
||||
if (recordMode == RecordMode.COMPILE) return;
|
||||
savedRecorder = DisplayListManager.pauseRecording();
|
||||
} else if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, indices);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(glCtx, indices);
|
||||
return;
|
||||
}
|
||||
if (widensLineDraw(mode, indices.remaining())) {
|
||||
drawLinesAsQuads(glCtx, ImmediateModeRecorder.processDrawElementsFromAttribs(mode, indices.remaining(), GL11.GL_UNSIGNED_INT, MemoryUtilities.memAddress(indices)));
|
||||
return;
|
||||
}
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawElements(mode, indices);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDrawElements(int mode, ShortBuffer indices) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
CommandRecorder savedRecorder = null;
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
final IndexedDrawCapture capture = IndexedDrawCapture.createFromClientIndices(mode, indices.remaining(), GL11.GL_UNSIGNED_SHORT, MemoryUtilities.memAddress(indices), (long) indices.remaining() << 1);
|
||||
if (capture != null) DisplayListManager.recordIndexedDrawCapture(capture);
|
||||
if (recordMode == RecordMode.COMPILE) return;
|
||||
savedRecorder = DisplayListManager.pauseRecording();
|
||||
} else if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, indices);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(glCtx, indices);
|
||||
return;
|
||||
}
|
||||
if (widensLineDraw(mode, indices.remaining())) {
|
||||
drawLinesAsQuads(glCtx, ImmediateModeRecorder.processDrawElementsFromAttribs(mode, indices.remaining(), GL11.GL_UNSIGNED_SHORT, MemoryUtilities.memAddress(indices)));
|
||||
return;
|
||||
}
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawElements(mode, indices);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDrawElements(int mode, int count, int type, ByteBuffer indices) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
CommandRecorder savedRecorder = null;
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
final IndexedDrawCapture capture = IndexedDrawCapture.createFromClientIndices(mode, count, type, MemoryUtilities.memAddress(indices), indices.remaining());
|
||||
if (capture != null) DisplayListManager.recordIndexedDrawCapture(capture);
|
||||
if (recordMode == RecordMode.COMPILE) return;
|
||||
savedRecorder = DisplayListManager.pauseRecording();
|
||||
} else if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, count, type, indices);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(glCtx, count, type, indices);
|
||||
return;
|
||||
}
|
||||
if (widensLineDraw(mode, count)) {
|
||||
drawLinesAsQuads(glCtx, ImmediateModeRecorder.processDrawElementsFromAttribs(mode, count, type, MemoryUtilities.memAddress(indices)));
|
||||
return;
|
||||
}
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawElements(mode, count, type, indices);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDrawElements(int mode, int indices_count, int type, long indices_buffer_offset) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
drawCalls++;
|
||||
CommandRecorder savedRecorder = null;
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
// Core profile: a default VAO is generated at init and glBindVertexArray(0)
|
||||
// is redirected to it, so a VAO is always bound here -- no fallback branches.
|
||||
final IndexedDrawCapture capture = IndexedDrawCapture.create(mode, indices_count, type, indices_buffer_offset, glCtx.vaos.boundEBO);
|
||||
if (capture != null) {
|
||||
DisplayListManager.recordIndexedDrawCapture(capture);
|
||||
}
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
savedRecorder = DisplayListManager.pauseRecording();
|
||||
} else if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, indices_count, type, indices_buffer_offset);
|
||||
return;
|
||||
}
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (widensLineDraw(mode, indices_count)) {
|
||||
drawLinesAsQuads(glCtx, lineElementsFromBuffer(glCtx, mode, indices_count, type, indices_buffer_offset));
|
||||
return;
|
||||
}
|
||||
final boolean ffpExt = FfpExtendedAttribs.maybeBindIndexed(glCtx, mode, indices_count, type, indices_buffer_offset);
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTriangles(glCtx, indices_count, type, indices_buffer_offset);
|
||||
return;
|
||||
}
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawElements(mode, indices_count, type, indices_buffer_offset);
|
||||
} finally {
|
||||
if (ffpExt) FfpExtendedAttribs.unbind();
|
||||
}
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glMultiDrawElementsIndirect(int mode, int type, long indirect, int drawcount, int stride) {
|
||||
rejectExitCapture();
|
||||
drawCalls += drawcount;
|
||||
RENDER_BACKEND.multiDrawElementsIndirect(mode, type, indirect, drawcount, stride);
|
||||
}
|
||||
|
||||
public static void glMultiDrawElementsBaseVertex(int mode, long pCount, int type, long pIndices, int drawcount, long pBaseVertex) {
|
||||
rejectExitCapture();
|
||||
drawCalls += drawcount;
|
||||
RENDER_BACKEND.multiDrawElementsBaseVertex(mode, pCount, type, pIndices, drawcount, pBaseVertex);
|
||||
}
|
||||
|
||||
public static void glDrawElementsBaseVertex(int mode, int count, int type, long indices, int basevertex) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
RENDER_BACKEND.drawElementsBaseVertex(mode, count, type, indices, basevertex);
|
||||
}
|
||||
|
||||
public static void glDrawElementsInstanced(int mode, int count, int type, long indices, int primcount) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadElementsAsTrianglesInstanced(glCtx, count, type, indices, primcount);
|
||||
return;
|
||||
}
|
||||
warnIfInstancedWideLines(mode);
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawElementsInstanced(mode, count, type, indices, primcount);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDrawArraysInstanced(int mode, int first, int count, int primcount) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadsAsTrianglesInstanced(glCtx, first, count, primcount);
|
||||
} else if (mode == GL11.GL_QUAD_STRIP) {
|
||||
preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
RENDER_BACKEND.drawArraysInstanced(GL11.GL_TRIANGLE_STRIP, first, count & ~1, primcount);
|
||||
} else if (mode == GL11.GL_POLYGON) {
|
||||
preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
RENDER_BACKEND.drawArraysInstanced(GL11.GL_TRIANGLE_FAN, first, count, primcount);
|
||||
} else {
|
||||
warnIfInstancedWideLines(mode);
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawArraysInstanced(mode, first, count, primcount);
|
||||
}
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDrawRangeElements(int mode, int start, int end, int count, int type, long indices) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (widensLineDraw(mode, count)) {
|
||||
drawLinesAsQuads(glCtx, lineElementsFromBuffer(glCtx, mode, count, type, indices));
|
||||
return;
|
||||
}
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawRangeElements(mode, start, end, count, type, indices);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDrawRangeElementsBaseVertex(int mode, int start, int end, int count, int type, long indices, int baseVertex) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.drawRangeElementsBaseVertex(mode, start, end, count, type, indices, baseVertex);
|
||||
}
|
||||
|
||||
public static void glMultiDrawArrays(int mode, IntBuffer firsts, IntBuffer counts) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (LineQuads.isLineMode(mode) && ffpWidensLineQuads()) {
|
||||
for (int i = firsts.position(); i < firsts.limit(); i++) {
|
||||
final int count = counts.get(counts.position() + i - firsts.position());
|
||||
if (LineQuads.segmentCount(mode, count) == 0) continue;
|
||||
drawLinesAsQuads(glCtx, ImmediateModeRecorder.processDrawArraysFromAttribs(mode, firsts.get(i), count));
|
||||
}
|
||||
return;
|
||||
}
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.multiDrawArrays(mode, firsts, counts);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glPrimitiveRestartIndex(int index) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.primitiveRestartIndex(index);
|
||||
}
|
||||
|
||||
public static void glDrawArrays(int mode, int first, int count) {
|
||||
rejectExitCapture();
|
||||
drawCalls++;
|
||||
CommandRecorder savedRecorder = null;
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
final DirectTessellator result = ImmediateModeRecorder.processDrawArraysFromAttribs(mode, first, count);
|
||||
if (result != null) {
|
||||
DisplayListManager.addImmediateModeDraw(result);
|
||||
}
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
DisplayListManager.flushAll();
|
||||
savedRecorder = DisplayListManager.pauseRecording();
|
||||
} else if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawArrays(mode, first, count);
|
||||
return;
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (widensLineDraw(mode, count)) {
|
||||
drawLinesAsQuads(glCtx, ImmediateModeRecorder.processDrawArraysFromAttribs(mode, first, count));
|
||||
return;
|
||||
}
|
||||
final boolean ffpExt = FfpExtendedAttribs.maybeBind(glCtx, mode, first, count);
|
||||
try {
|
||||
if (mode == GL11.GL_QUADS) {
|
||||
QuadConverter.drawQuadsAsTriangles(glCtx, first, count);
|
||||
} else if (mode == GL11.GL_QUAD_STRIP) {
|
||||
preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_STRIP, first, count & ~1);
|
||||
} else if (mode == GL11.GL_POLYGON) {
|
||||
preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
RENDER_BACKEND.drawArrays(GL11.GL_TRIANGLE_FAN, first, count);
|
||||
} else {
|
||||
preDraw(glCtx, mode);
|
||||
RENDER_BACKEND.drawArrays(mode, first, count);
|
||||
}
|
||||
} finally {
|
||||
if (ffpExt) FfpExtendedAttribs.unbind();
|
||||
}
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
if (savedRecorder != null) DisplayListManager.resumeRecording(savedRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glNewList(int list, int mode) {
|
||||
rejectExitCapture();
|
||||
DisplayListManager.glNewList(list, mode);
|
||||
}
|
||||
|
||||
public static void glEndList() {
|
||||
rejectExitCapture();
|
||||
DisplayListManager.glEndList();
|
||||
}
|
||||
|
||||
static final DisplayListIDAllocator displayListIdAllocator = new DisplayListIDAllocator();
|
||||
|
||||
public static int glGenLists(int range) {
|
||||
rejectExitCapture();
|
||||
return displayListIdAllocator.allocRange(range);
|
||||
}
|
||||
|
||||
public static boolean glIsList(int list) {
|
||||
rejectExitCapture();
|
||||
return displayListIdAllocator.isAllocated(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete display lists and free their VBO resources.
|
||||
*/
|
||||
public static void glDeleteLists(int list, int range) {
|
||||
rejectExitCapture();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
synchronized (displayListIdAllocator) {
|
||||
DisplayListManager.glDeleteLists(list, range);
|
||||
displayListIdAllocator.freeRange(list, range);
|
||||
}
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a compiled display list from the cache. Used for executing nested display lists.
|
||||
*
|
||||
* @param list The display list ID
|
||||
* @return The CompiledDisplayList, or null if not found
|
||||
*/
|
||||
public static CompiledDisplayList getDisplayList(int list) {
|
||||
return DisplayListManager.getDisplayList(list);
|
||||
}
|
||||
|
||||
public static void glCallList(int list) {
|
||||
rejectExitCapture();
|
||||
if (!GLDebug.isActive()) {
|
||||
DisplayListManager.glCallList(list);
|
||||
return;
|
||||
}
|
||||
GLDebug.pushGroup("glCallList ", list);
|
||||
try {
|
||||
DisplayListManager.glCallList(list);
|
||||
} finally {
|
||||
GLDebug.popGroup();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getListMode() {
|
||||
return DisplayListManager.getListMode();
|
||||
}
|
||||
|
||||
public static boolean ffpWidensLineQuads() {
|
||||
final GLContextState glCtx = ctx();
|
||||
return GLSMRasterizer.wideLineEmulationEnabled && glCtx.activeProgram == 0 && glCtx.lineState.getWidth() > 1.0f
|
||||
&& !DisplayListManager.isRecording();
|
||||
}
|
||||
|
||||
private static boolean widensLineDraw(int mode, int count) {
|
||||
return LineQuads.isLineMode(mode) && LineQuads.segmentCount(mode, count) > 0 && ffpWidensLineQuads();
|
||||
}
|
||||
|
||||
private static void drawLinesAsQuads(GLContextState glCtx, DirectTessellator lines) {
|
||||
if (lines == null) return;
|
||||
if (readsBufferObject(glCtx.vaos)) {
|
||||
warnOnce("line-readback", "Wide GL_LINES drawn from a buffer object; widening them reads the buffer back, which waits for the GPU");
|
||||
}
|
||||
final int vao = glCtx.boundVAO;
|
||||
final int vbo = glCtx.boundVBO;
|
||||
TessellatorStreamingDrawer.drawDirect(lines);
|
||||
GLSMVertexInput.glBindVertexArray(vao);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
}
|
||||
|
||||
private static DirectTessellator lineElementsFromBuffer(GLContextState glCtx, int mode, int count, int type, long offset) {
|
||||
if (glCtx.vaos.boundEBO == 0) return null;
|
||||
final ByteBuffer indices = MemoryUtilities.memAlloc(count * GLTypes.sizeBytes(type));
|
||||
try {
|
||||
GLSMBuffers.glGetBufferSubData(GL15.GL_ELEMENT_ARRAY_BUFFER, offset, indices);
|
||||
return ImmediateModeRecorder.processDrawElementsFromAttribs(mode, count, type, MemoryUtilities.memAddress0(indices));
|
||||
} finally {
|
||||
MemoryUtilities.memFree(indices);
|
||||
}
|
||||
}
|
||||
|
||||
private static void warnIfInstancedWideLines(int mode) {
|
||||
if (LineQuads.isLineMode(mode) && ffpWidensLineQuads()) {
|
||||
warnOnce("instanced-wide-lines", "Instanced wide GL_LINES are not widened and draw 1 px wide");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean readsBufferObject(VAOManager vaos) {
|
||||
for (int i = 0; i < VAOManager.MAX_ATTRIBS; i++) {
|
||||
final VAOManager.Attrib attrib = vaos.attrib(i);
|
||||
if (attrib != null && attrib.enabled && attrib.vboId != 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void prepareLineEmulation(GLContextState glCtx, int drawMode) {
|
||||
setLineStippleActive(glCtx, (LineQuads.isLineMode(drawMode) || glCtx.lineQuadsActive) && glCtx.lineStippleState.isEnabled());
|
||||
}
|
||||
|
||||
private static void setLineStippleActive(GLContextState glCtx, boolean active) {
|
||||
if (glCtx.lineStippleActive == active) return;
|
||||
glCtx.lineStippleActive = active;
|
||||
RENDER_BACKEND.provokingVertex(active ? GL32.GL_FIRST_VERTEX_CONVENTION : GL32.GL_LAST_VERTEX_CONVENTION);
|
||||
}
|
||||
|
||||
public static void glFlush() {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.flush();
|
||||
}
|
||||
|
||||
public static void glFinish() {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.finish();
|
||||
}
|
||||
|
||||
public static void glMultiDrawArraysIndirectCount(int mode, long indirect, long drawcount, int maxdrawcount, int stride) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.multiDrawArraysIndirectCount(mode, indirect, drawcount, maxdrawcount, stride);
|
||||
}
|
||||
|
||||
public static void glMultiDrawElementsIndirectCount(int mode, int type, long indirect, long drawcount, int maxdrawcount, int stride) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.multiDrawElementsIndirectCount(mode, type, indirect, drawcount, maxdrawcount, stride);
|
||||
}
|
||||
|
||||
public static void glCallLists(IntBuffer lists) {
|
||||
while (lists.hasRemaining()) {
|
||||
final int listId = lists.get() + ctx().listBase;
|
||||
glCallList(listId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glCallLists(ShortBuffer lists) {
|
||||
while (lists.hasRemaining()) {
|
||||
final int listId = (lists.get() & 0xFFFF) + ctx().listBase;
|
||||
glCallList(listId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glCallLists(ByteBuffer lists) {
|
||||
while (lists.hasRemaining()) {
|
||||
final int listId = (lists.get() & 0xFF) + ctx().listBase;
|
||||
glCallList(listId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glListBase(int base) {
|
||||
rejectExitCapture();
|
||||
ctx().listBase = base;
|
||||
}
|
||||
public static void nglMultiDrawElementsBaseVertex(int mode, long count, int type, long indices, int primcount, long basevertex) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.multiDrawElementsBaseVertex(mode, count, type, indices, primcount, basevertex);
|
||||
}
|
||||
|
||||
public static void glObjectLabel(int identifier, int name, CharSequence label) { RENDER_BACKEND.objectLabel(identifier, name, label); }
|
||||
public static String glGetObjectLabel(int identifier, int name, int bufSize) { rejectExitCapture(); return RENDER_BACKEND.getObjectLabel(identifier, name); }
|
||||
public static void glPushDebugGroup(int source, int id, CharSequence message) { RENDER_BACKEND.pushDebugGroup(source, id, message); }
|
||||
public static void glPopDebugGroup() { RENDER_BACKEND.popDebugGroup(); }
|
||||
public static void glDebugMessageInsert(int source, int type, int id, int severity, CharSequence buf) { RENDER_BACKEND.debugMessageInsert(source, type, id, severity, buf); }
|
||||
public static void glDebugMessageControl(int source, int type, int severity, IntBuffer ids, boolean enabled) { RENDER_BACKEND.debugMessageControl(source, type, severity, ids, enabled); }
|
||||
|
||||
public static int glGetDebugMessageLog(int count, IntBuffer sources, IntBuffer types, IntBuffer ids, IntBuffer severities, IntBuffer lengths, ByteBuffer messageLog) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getDebugMessageLog(count, sources, types, ids, severities, lengths, messageLog);
|
||||
}
|
||||
|
||||
public static void registerDebugMessageListener(GLDebugMessageListener listener, long userParam) {
|
||||
RENDER_BACKEND.debugMessageCallback(listener, userParam);
|
||||
}
|
||||
|
||||
public static void glDebugMessageCallback(KHRDebugCallback callback) {
|
||||
RENDER_BACKEND.debugMessageCallback(GLDebug.adaptDebugCallback(callback), 0L);
|
||||
}
|
||||
|
||||
public static void glAccum(int op, float value) {
|
||||
guardUnsupportedFFP("glAccum", "The accumulation buffer is not available in GL 3.3 core profile.");
|
||||
}
|
||||
|
||||
public static void glFeedbackBuffer(int type, FloatBuffer buffer) {
|
||||
rejectExitCapture();
|
||||
FeedbackManager.glFeedbackBuffer(type, buffer);
|
||||
}
|
||||
|
||||
public static int glRenderMode(int mode) {
|
||||
rejectExitCapture();
|
||||
return FeedbackManager.glRenderMode(mode);
|
||||
}
|
||||
|
||||
public static void glPassThrough(float token) {
|
||||
rejectExitCapture();
|
||||
FeedbackManager.glPassThrough(token);
|
||||
}
|
||||
|
||||
private static boolean selectWarned = false;
|
||||
|
||||
public static void glSelectBuffer(IntBuffer buffer) {
|
||||
rejectExitCapture();
|
||||
if (!selectWarned) {
|
||||
LOGGER.warn("glSelectBuffer: selection mode not emulated");
|
||||
selectWarned = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glInitNames() { /* no-op: ignored outside GL_SELECT */ }
|
||||
|
||||
public static void glPushName(int name) { /* no-op */ }
|
||||
|
||||
public static void glPopName() { /* no-op */ }
|
||||
|
||||
public static void glLoadName(int name) { /* no-op */ }
|
||||
|
||||
/**
|
||||
* Draw modes that rely on the previous vertex data cannot be merged currently.
|
||||
* It is possible to merge them using Index Buffers, but currently unimplemented.
|
||||
*/
|
||||
public static boolean isContinuousDraw(int drawMode) {
|
||||
return drawMode == GL11.GL_TRIANGLE_STRIP || drawMode == GL11.GL_TRIANGLE_FAN
|
||||
|| drawMode == GL11.GL_LINE_STRIP || drawMode == GL11.GL_LINE_LOOP
|
||||
|| drawMode == GL11.GL_QUAD_STRIP || drawMode == GL11.GL_POLYGON;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
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 static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_CLIP_PLANES;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMEnable {
|
||||
|
||||
private GLSMEnable() {}
|
||||
|
||||
public static void glEnable(int cap) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(cap);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Handle clip planes dynamically (supports up to MAX_CLIP_PLANES)
|
||||
if (cap >= GL11.GL_CLIP_PLANE0 && cap < GL11.GL_CLIP_PLANE0 + MAX_CLIP_PLANES) {
|
||||
glCtx.clipPlaneStates[cap - GL11.GL_CLIP_PLANE0].enable();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cap) {
|
||||
case GL11.GL_ALPHA_TEST -> GLSMDepthStencilAlpha.enableAlphaTest(glCtx);
|
||||
case GL11.GL_AUTO_NORMAL -> glCtx.autoNormalState.enable();
|
||||
case GL11.GL_BLEND -> GLSMBlend.enableBlend(glCtx);
|
||||
case GL11.GL_COLOR_MATERIAL -> GLSMLighting.enableColorMaterial(glCtx);
|
||||
case GL11.GL_COLOR_LOGIC_OP -> glCtx.colorLogicOpState.enable();
|
||||
case GL14.GL_COLOR_SUM -> glCtx.colorSumState.enable();
|
||||
case GL11.GL_CULL_FACE -> GLSMRasterizer.enableCull(glCtx);
|
||||
case GL11.GL_DEPTH_TEST -> GLSMDepthStencilAlpha.enableDepthTest(glCtx);
|
||||
case GL11.GL_DITHER -> glCtx.ditherState.enable();
|
||||
case GL11.GL_FOG -> GLSMFog.enableFog(glCtx);
|
||||
case GL11.GL_INDEX_LOGIC_OP -> glCtx.indexLogicOpState.enable();
|
||||
case GL11.GL_LIGHTING -> GLSMLighting.enableLighting(glCtx);
|
||||
case GL11.GL_LIGHT0 -> GLSMLighting.enableLight(glCtx, 0);
|
||||
case GL11.GL_LIGHT1 -> GLSMLighting.enableLight(glCtx, 1);
|
||||
case GL11.GL_LIGHT2 -> GLSMLighting.enableLight(glCtx, 2);
|
||||
case GL11.GL_LIGHT3 -> GLSMLighting.enableLight(glCtx, 3);
|
||||
case GL11.GL_LIGHT4 -> GLSMLighting.enableLight(glCtx, 4);
|
||||
case GL11.GL_LIGHT5 -> GLSMLighting.enableLight(glCtx, 5);
|
||||
case GL11.GL_LIGHT6 -> GLSMLighting.enableLight(glCtx, 6);
|
||||
case GL11.GL_LIGHT7 -> GLSMLighting.enableLight(glCtx, 7);
|
||||
case GL11.GL_LINE_SMOOTH -> glCtx.lineSmoothState.enable();
|
||||
case GL11.GL_LINE_STIPPLE -> glCtx.lineStippleState.enable();
|
||||
case GL11.GL_MAP1_COLOR_4 -> glCtx.map1Color4State.enable();
|
||||
case GL11.GL_MAP1_INDEX -> glCtx.map1IndexState.enable();
|
||||
case GL11.GL_MAP1_NORMAL -> glCtx.map1NormalState.enable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_1 -> glCtx.map1TextureCoord1State.enable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_2 -> glCtx.map1TextureCoord2State.enable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_3 -> glCtx.map1TextureCoord3State.enable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_4 -> glCtx.map1TextureCoord4State.enable();
|
||||
case GL11.GL_MAP1_VERTEX_3 -> glCtx.map1Vertex3State.enable();
|
||||
case GL11.GL_MAP1_VERTEX_4 -> glCtx.map1Vertex4State.enable();
|
||||
case GL11.GL_MAP2_COLOR_4 -> glCtx.map2Color4State.enable();
|
||||
case GL11.GL_MAP2_INDEX -> glCtx.map2IndexState.enable();
|
||||
case GL11.GL_MAP2_NORMAL -> glCtx.map2NormalState.enable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_1 -> glCtx.map2TextureCoord1State.enable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_2 -> glCtx.map2TextureCoord2State.enable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_3 -> glCtx.map2TextureCoord3State.enable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_4 -> glCtx.map2TextureCoord4State.enable();
|
||||
case GL11.GL_MAP2_VERTEX_3 -> glCtx.map2Vertex3State.enable();
|
||||
case GL11.GL_MAP2_VERTEX_4 -> glCtx.map2Vertex4State.enable();
|
||||
case GL13.GL_MULTISAMPLE -> glCtx.multisampleState.enable();
|
||||
case GL11.GL_NORMALIZE -> glCtx.normalizeState.enable();
|
||||
case GL11.GL_POINT_SMOOTH -> glCtx.pointSmoothState.enable();
|
||||
case GL20.GL_POINT_SPRITE -> glCtx.pointSpriteState.enable();
|
||||
case GL20.GL_VERTEX_PROGRAM_TWO_SIDE -> glCtx.vertexProgramTwoSideState.enable();
|
||||
case GL11.GL_POLYGON_OFFSET_POINT -> glCtx.polygonOffsetPointState.enable();
|
||||
case GL11.GL_POLYGON_OFFSET_LINE -> glCtx.polygonOffsetLineState.enable();
|
||||
case GL11.GL_POLYGON_OFFSET_FILL -> glCtx.polygonOffsetFillState.enable();
|
||||
case GL11.GL_POLYGON_SMOOTH -> glCtx.polygonSmoothState.enable();
|
||||
case GL11.GL_POLYGON_STIPPLE -> glCtx.polygonStippleState.enable();
|
||||
case GL12.GL_RESCALE_NORMAL -> GLSMLighting.enableRescaleNormal(glCtx);
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_COVERAGE -> glCtx.sampleAlphaToCoverageState.enable();
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_ONE -> glCtx.sampleAlphaToOneState.enable();
|
||||
case GL13.GL_SAMPLE_COVERAGE -> glCtx.sampleCoverageState.enable();
|
||||
case GL30.GL_RASTERIZER_DISCARD -> glCtx.rasterizerDiscard.enable();
|
||||
case GL11.GL_SCISSOR_TEST -> GLSMRasterizer.enableScissorTest(glCtx);
|
||||
case GL11.GL_STENCIL_TEST -> glCtx.stencilTest.enable();
|
||||
case GL11.GL_TEXTURE_1D -> glCtx.textures.getTexture1DStates(glCtx.activeTextureUnit.getValue()).enable();
|
||||
case GL11.GL_TEXTURE_2D -> GLSMTextures.enableTexture(glCtx);
|
||||
case GL12.GL_TEXTURE_3D -> glCtx.textures.getTexture3DStates(glCtx.activeTextureUnit.getValue()).enable();
|
||||
case GL13.GL_TEXTURE_CUBE_MAP -> glCtx.textures.getTextureCubeMapStates(glCtx.activeTextureUnit.getValue()).enable();
|
||||
case GL11.GL_TEXTURE_GEN_S -> glCtx.textures.getTexGenSStates(glCtx.activeTextureUnit.getValue()).enable();
|
||||
case GL11.GL_TEXTURE_GEN_T -> glCtx.textures.getTexGenTStates(glCtx.activeTextureUnit.getValue()).enable();
|
||||
case GL11.GL_TEXTURE_GEN_R -> glCtx.textures.getTexGenRStates(glCtx.activeTextureUnit.getValue()).enable();
|
||||
case GL11.GL_TEXTURE_GEN_Q -> glCtx.textures.getTexGenQStates(glCtx.activeTextureUnit.getValue()).enable();
|
||||
default -> {
|
||||
glCtx.exitCapture.reject();
|
||||
if (!GLSMVertexInput.setClientArrayCap(glCtx, cap, true)) RENDER_BACKEND.enable(cap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDisable(int cap) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(cap);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Handle clip planes dynamically (supports up to MAX_CLIP_PLANES)
|
||||
if (cap >= GL11.GL_CLIP_PLANE0 && cap < GL11.GL_CLIP_PLANE0 + MAX_CLIP_PLANES) {
|
||||
glCtx.clipPlaneStates[cap - GL11.GL_CLIP_PLANE0].disable();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (cap) {
|
||||
case GL11.GL_ALPHA_TEST -> GLSMDepthStencilAlpha.disableAlphaTest(glCtx);
|
||||
case GL11.GL_AUTO_NORMAL -> glCtx.autoNormalState.disable();
|
||||
case GL11.GL_BLEND -> GLSMBlend.disableBlend(glCtx);
|
||||
case GL11.GL_COLOR_MATERIAL -> GLSMLighting.disableColorMaterial(glCtx);
|
||||
case GL11.GL_COLOR_LOGIC_OP -> glCtx.colorLogicOpState.disable();
|
||||
case GL14.GL_COLOR_SUM -> glCtx.colorSumState.disable();
|
||||
case GL11.GL_CULL_FACE -> GLSMRasterizer.disableCull(glCtx);
|
||||
case GL11.GL_DEPTH_TEST -> GLSMDepthStencilAlpha.disableDepthTest(glCtx);
|
||||
case GL11.GL_DITHER -> glCtx.ditherState.disable();
|
||||
case GL11.GL_FOG -> GLSMFog.disableFog(glCtx);
|
||||
case GL11.GL_INDEX_LOGIC_OP -> glCtx.indexLogicOpState.disable();
|
||||
case GL11.GL_LIGHTING -> GLSMLighting.disableLighting(glCtx);
|
||||
case GL11.GL_LIGHT0 -> GLSMLighting.disableLight(glCtx, 0);
|
||||
case GL11.GL_LIGHT1 -> GLSMLighting.disableLight(glCtx, 1);
|
||||
case GL11.GL_LIGHT2 -> GLSMLighting.disableLight(glCtx, 2);
|
||||
case GL11.GL_LIGHT3 -> GLSMLighting.disableLight(glCtx, 3);
|
||||
case GL11.GL_LIGHT4 -> GLSMLighting.disableLight(glCtx, 4);
|
||||
case GL11.GL_LIGHT5 -> GLSMLighting.disableLight(glCtx, 5);
|
||||
case GL11.GL_LIGHT6 -> GLSMLighting.disableLight(glCtx, 6);
|
||||
case GL11.GL_LIGHT7 -> GLSMLighting.disableLight(glCtx, 7);
|
||||
case GL11.GL_LINE_SMOOTH -> glCtx.lineSmoothState.disable();
|
||||
case GL11.GL_LINE_STIPPLE -> glCtx.lineStippleState.disable();
|
||||
case GL11.GL_MAP1_COLOR_4 -> glCtx.map1Color4State.disable();
|
||||
case GL11.GL_MAP1_INDEX -> glCtx.map1IndexState.disable();
|
||||
case GL11.GL_MAP1_NORMAL -> glCtx.map1NormalState.disable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_1 -> glCtx.map1TextureCoord1State.disable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_2 -> glCtx.map1TextureCoord2State.disable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_3 -> glCtx.map1TextureCoord3State.disable();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_4 -> glCtx.map1TextureCoord4State.disable();
|
||||
case GL11.GL_MAP1_VERTEX_3 -> glCtx.map1Vertex3State.disable();
|
||||
case GL11.GL_MAP1_VERTEX_4 -> glCtx.map1Vertex4State.disable();
|
||||
case GL11.GL_MAP2_COLOR_4 -> glCtx.map2Color4State.disable();
|
||||
case GL11.GL_MAP2_INDEX -> glCtx.map2IndexState.disable();
|
||||
case GL11.GL_MAP2_NORMAL -> glCtx.map2NormalState.disable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_1 -> glCtx.map2TextureCoord1State.disable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_2 -> glCtx.map2TextureCoord2State.disable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_3 -> glCtx.map2TextureCoord3State.disable();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_4 -> glCtx.map2TextureCoord4State.disable();
|
||||
case GL11.GL_MAP2_VERTEX_3 -> glCtx.map2Vertex3State.disable();
|
||||
case GL11.GL_MAP2_VERTEX_4 -> glCtx.map2Vertex4State.disable();
|
||||
case GL13.GL_MULTISAMPLE -> glCtx.multisampleState.disable();
|
||||
case GL11.GL_NORMALIZE -> glCtx.normalizeState.disable();
|
||||
case GL11.GL_POINT_SMOOTH -> glCtx.pointSmoothState.disable();
|
||||
case GL20.GL_POINT_SPRITE -> glCtx.pointSpriteState.disable();
|
||||
case GL20.GL_VERTEX_PROGRAM_TWO_SIDE -> glCtx.vertexProgramTwoSideState.disable();
|
||||
case GL11.GL_POLYGON_OFFSET_POINT -> glCtx.polygonOffsetPointState.disable();
|
||||
case GL11.GL_POLYGON_OFFSET_LINE -> glCtx.polygonOffsetLineState.disable();
|
||||
case GL11.GL_POLYGON_OFFSET_FILL -> glCtx.polygonOffsetFillState.disable();
|
||||
case GL11.GL_POLYGON_SMOOTH -> glCtx.polygonSmoothState.disable();
|
||||
case GL11.GL_POLYGON_STIPPLE -> glCtx.polygonStippleState.disable();
|
||||
case GL12.GL_RESCALE_NORMAL -> GLSMLighting.disableRescaleNormal(glCtx);
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_COVERAGE -> glCtx.sampleAlphaToCoverageState.disable();
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_ONE -> glCtx.sampleAlphaToOneState.disable();
|
||||
case GL13.GL_SAMPLE_COVERAGE -> glCtx.sampleCoverageState.disable();
|
||||
case GL30.GL_RASTERIZER_DISCARD -> glCtx.rasterizerDiscard.disable();
|
||||
case GL11.GL_SCISSOR_TEST -> GLSMRasterizer.disableScissorTest(glCtx);
|
||||
case GL11.GL_STENCIL_TEST -> glCtx.stencilTest.disable();
|
||||
case GL11.GL_TEXTURE_1D -> glCtx.textures.getTexture1DStates(glCtx.activeTextureUnit.getValue()).disable();
|
||||
case GL11.GL_TEXTURE_2D -> GLSMTextures.disableTexture(glCtx);
|
||||
case GL12.GL_TEXTURE_3D -> glCtx.textures.getTexture3DStates(glCtx.activeTextureUnit.getValue()).disable();
|
||||
case GL13.GL_TEXTURE_CUBE_MAP -> glCtx.textures.getTextureCubeMapStates(glCtx.activeTextureUnit.getValue()).disable();
|
||||
case GL11.GL_TEXTURE_GEN_S -> glCtx.textures.getTexGenSStates(glCtx.activeTextureUnit.getValue()).disable();
|
||||
case GL11.GL_TEXTURE_GEN_T -> glCtx.textures.getTexGenTStates(glCtx.activeTextureUnit.getValue()).disable();
|
||||
case GL11.GL_TEXTURE_GEN_R -> glCtx.textures.getTexGenRStates(glCtx.activeTextureUnit.getValue()).disable();
|
||||
case GL11.GL_TEXTURE_GEN_Q -> glCtx.textures.getTexGenQStates(glCtx.activeTextureUnit.getValue()).disable();
|
||||
default -> {
|
||||
glCtx.exitCapture.reject();
|
||||
if (!GLSMVertexInput.setClientArrayCap(glCtx, cap, false)) RENDER_BACKEND.disable(cap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean glIsEnabled(int cap) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) {
|
||||
return RENDER_BACKEND.getBoolean(cap);
|
||||
}
|
||||
// Handle clip planes dynamically (supports up to MAX_CLIP_PLANES)
|
||||
if (cap >= GL11.GL_CLIP_PLANE0 && cap < GL11.GL_CLIP_PLANE0 + MAX_CLIP_PLANES) {
|
||||
return glCtx.clipPlaneStates[cap - GL11.GL_CLIP_PLANE0].isEnabled();
|
||||
}
|
||||
|
||||
return switch (cap) {
|
||||
case GL11.GL_ALPHA_TEST -> glCtx.alphaTest.isEnabled();
|
||||
case GL11.GL_AUTO_NORMAL -> glCtx.autoNormalState.isEnabled();
|
||||
case GL11.GL_BLEND -> glCtx.blendMode.isEnabled();
|
||||
case GL11.GL_COLOR_MATERIAL -> glCtx.colorMaterial.isEnabled();
|
||||
case GL11.GL_COLOR_LOGIC_OP -> glCtx.colorLogicOpState.isEnabled();
|
||||
case GL14.GL_COLOR_SUM -> glCtx.colorSumState.isEnabled();
|
||||
case GL11.GL_CULL_FACE -> glCtx.cullState.isEnabled();
|
||||
case GL11.GL_DEPTH_TEST -> glCtx.depthTest.isEnabled();
|
||||
case GL11.GL_DITHER -> glCtx.ditherState.isEnabled();
|
||||
case GL11.GL_FOG -> glCtx.fogMode.isEnabled();
|
||||
case GL11.GL_INDEX_LOGIC_OP -> glCtx.indexLogicOpState.isEnabled();
|
||||
case GL11.GL_LIGHTING -> glCtx.lightingState.isEnabled();
|
||||
case GL11.GL_LIGHT0 -> glCtx.lightStates[0].isEnabled();
|
||||
case GL11.GL_LIGHT1 -> glCtx.lightStates[1].isEnabled();
|
||||
case GL11.GL_LIGHT2 -> glCtx.lightStates[2].isEnabled();
|
||||
case GL11.GL_LIGHT3 -> glCtx.lightStates[3].isEnabled();
|
||||
case GL11.GL_LIGHT4 -> glCtx.lightStates[4].isEnabled();
|
||||
case GL11.GL_LIGHT5 -> glCtx.lightStates[5].isEnabled();
|
||||
case GL11.GL_LIGHT6 -> glCtx.lightStates[6].isEnabled();
|
||||
case GL11.GL_LIGHT7 -> glCtx.lightStates[7].isEnabled();
|
||||
case GL11.GL_LINE_SMOOTH -> glCtx.lineSmoothState.isEnabled();
|
||||
case GL11.GL_LINE_STIPPLE -> glCtx.lineStippleState.isEnabled();
|
||||
case GL11.GL_MAP1_COLOR_4 -> glCtx.map1Color4State.isEnabled();
|
||||
case GL11.GL_MAP1_INDEX -> glCtx.map1IndexState.isEnabled();
|
||||
case GL11.GL_MAP1_NORMAL -> glCtx.map1NormalState.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_1 -> glCtx.map1TextureCoord1State.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_2 -> glCtx.map1TextureCoord2State.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_3 -> glCtx.map1TextureCoord3State.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_4 -> glCtx.map1TextureCoord4State.isEnabled();
|
||||
case GL11.GL_MAP1_VERTEX_3 -> glCtx.map1Vertex3State.isEnabled();
|
||||
case GL11.GL_MAP1_VERTEX_4 -> glCtx.map1Vertex4State.isEnabled();
|
||||
case GL11.GL_MAP2_COLOR_4 -> glCtx.map2Color4State.isEnabled();
|
||||
case GL11.GL_MAP2_INDEX -> glCtx.map2IndexState.isEnabled();
|
||||
case GL11.GL_MAP2_NORMAL -> glCtx.map2NormalState.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_1 -> glCtx.map2TextureCoord1State.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_2 -> glCtx.map2TextureCoord2State.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_3 -> glCtx.map2TextureCoord3State.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_4 -> glCtx.map2TextureCoord4State.isEnabled();
|
||||
case GL11.GL_MAP2_VERTEX_3 -> glCtx.map2Vertex3State.isEnabled();
|
||||
case GL11.GL_MAP2_VERTEX_4 -> glCtx.map2Vertex4State.isEnabled();
|
||||
case GL13.GL_MULTISAMPLE -> glCtx.multisampleState.isEnabled();
|
||||
case GL11.GL_NORMALIZE -> glCtx.normalizeState.isEnabled();
|
||||
case GL11.GL_POINT_SMOOTH -> glCtx.pointSmoothState.isEnabled();
|
||||
case GL20.GL_POINT_SPRITE -> glCtx.pointSpriteState.isEnabled();
|
||||
case GL20.GL_VERTEX_PROGRAM_TWO_SIDE -> glCtx.vertexProgramTwoSideState.isEnabled();
|
||||
case GL11.GL_POLYGON_OFFSET_POINT -> glCtx.polygonOffsetPointState.isEnabled();
|
||||
case GL11.GL_POLYGON_OFFSET_LINE -> glCtx.polygonOffsetLineState.isEnabled();
|
||||
case GL11.GL_POLYGON_OFFSET_FILL -> glCtx.polygonOffsetFillState.isEnabled();
|
||||
case GL11.GL_POLYGON_SMOOTH -> glCtx.polygonSmoothState.isEnabled();
|
||||
case GL11.GL_POLYGON_STIPPLE -> glCtx.polygonStippleState.isEnabled();
|
||||
case GL12.GL_RESCALE_NORMAL -> glCtx.rescaleNormalState.isEnabled();
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_COVERAGE -> glCtx.sampleAlphaToCoverageState.isEnabled();
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_ONE -> glCtx.sampleAlphaToOneState.isEnabled();
|
||||
case GL13.GL_SAMPLE_COVERAGE -> glCtx.sampleCoverageState.isEnabled();
|
||||
case GL30.GL_RASTERIZER_DISCARD -> glCtx.rasterizerDiscard.isEnabled();
|
||||
case GL11.GL_SCISSOR_TEST -> glCtx.scissorTest.isEnabled();
|
||||
case GL11.GL_STENCIL_TEST -> glCtx.stencilTest.isEnabled();
|
||||
case GL11.GL_TEXTURE_1D -> glCtx.textures.getTexture1DStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_2D -> glCtx.textures.getTextureUnitStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL12.GL_TEXTURE_3D -> glCtx.textures.getTexture3DStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL13.GL_TEXTURE_CUBE_MAP -> glCtx.textures.getTextureCubeMapStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_S -> glCtx.textures.getTexGenSStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_T -> glCtx.textures.getTexGenTStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_R -> glCtx.textures.getTexGenRStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_Q -> glCtx.textures.getTexGenQStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
default -> {
|
||||
final int conv = GLSMVertexInput.clientStateToConventional(glCtx, cap);
|
||||
yield conv >= 0 ? glCtx.vaos.isConventionalEnabled(conv) : LegacyQueries.desc(cap) == 0 && RENDER_BACKEND.getBoolean(cap);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void glEnablei(int cap, int index) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.enablei(cap, index);
|
||||
markIndexedCapUnknown(cap);
|
||||
}
|
||||
|
||||
public static void glDisablei(int cap, int index) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.disablei(cap, index);
|
||||
markIndexedCapUnknown(cap);
|
||||
}
|
||||
|
||||
private static void markIndexedCapUnknown(int cap) {
|
||||
if (cap == GL11.GL_BLEND) {
|
||||
ctx().blendMode.setUnknownState();
|
||||
} else if (cap == GL11.GL_SCISSOR_TEST) {
|
||||
ctx().scissorTest.setUnknownState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.FogStateStack;
|
||||
import org.joml.Vector3d;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.HAS_MULTIPLE_SET;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
|
||||
public final class GLSMFog {
|
||||
|
||||
private GLSMFog() {}
|
||||
|
||||
public static void enableFog() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_FOG);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableFog(ctx());
|
||||
}
|
||||
|
||||
static void enableFog(GLContextState glCtx) {
|
||||
glCtx.fogMode.enable();
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public static void disableFog() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_FOG);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableFog(ctx());
|
||||
}
|
||||
|
||||
static void disableFog(GLContextState glCtx) {
|
||||
glCtx.fogMode.disable();
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glFog(int pname, FloatBuffer param) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordFog(pname, param);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (HAS_MULTIPLE_SET.contains(pname)) {
|
||||
if (pname == GL11.GL_FOG_COLOR && isCachingEnabled()) {
|
||||
final float red = param.get(0);
|
||||
final float green = param.get(1);
|
||||
final float blue = param.get(2);
|
||||
|
||||
beforeUncapturedStateChange();
|
||||
mod(glCtx.fogState);
|
||||
glCtx.fogState.getFogColor().set(red, green, blue);
|
||||
glCtx.fogState.setFogAlpha(param.get(3));
|
||||
glCtx.fogState.getFogColorBuffer().clear();
|
||||
glCtx.fogState.getFogColorBuffer().put((FloatBuffer) param.position(0)).flip();
|
||||
glCtx.fragmentGeneration++;
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
glFogf(pname, param.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector3d getFogColor() {
|
||||
return ctx().fogState.getFogColor();
|
||||
}
|
||||
|
||||
public static void fogColor(float red, float green, float blue, float alpha) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || red != glCtx.fogState.getFogColor().x || green != glCtx.fogState.getFogColor().y || blue != glCtx.fogState.getFogColor().z || alpha != glCtx.fogState.getFogAlpha()) {
|
||||
beforeUncapturedStateChange();
|
||||
mod(glCtx.fogState);
|
||||
glCtx.fogState.getFogColor().set(red, green, blue);
|
||||
glCtx.fogState.setFogAlpha(alpha);
|
||||
glCtx.fogState.getFogColorBuffer().clear();
|
||||
glCtx.fogState.getFogColorBuffer().put(red).put(green).put(blue).put(alpha).flip();
|
||||
glCtx.fragmentGeneration++;
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glFogf(int pname, float param) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordFogf(pname, param);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Update cached state (FFP shader reads from cache)
|
||||
if (isCachingEnabled()) {
|
||||
boolean changed = false;
|
||||
switch (pname) {
|
||||
case GL11.GL_FOG_DENSITY -> { if (!isCachingEnabled() || glCtx.fogState.getDensity() != param) { beforeUncapturedStateChange(); mod(glCtx.fogState).setDensity(param); changed = true; } }
|
||||
case GL11.GL_FOG_START -> { if (!isCachingEnabled() || glCtx.fogState.getStart() != param) { beforeUncapturedStateChange(); mod(glCtx.fogState).setStart(param); changed = true; } }
|
||||
case GL11.GL_FOG_END -> { if (!isCachingEnabled() || glCtx.fogState.getEnd() != param) { beforeUncapturedStateChange(); mod(glCtx.fogState).setEnd(param); changed = true; } }
|
||||
case GL11.GL_FOG_MODE -> { if (!isCachingEnabled() || glCtx.fogState.getFogMode() != (int) param) { beforeUncapturedStateChange(); mod(glCtx.fogState).setFogMode((int) param); changed = true; } }
|
||||
default -> {}
|
||||
}
|
||||
if (changed) {
|
||||
glCtx.fragmentGeneration++;
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glFogi(int pname, int param) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordFogi(pname, param);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Update cached state (FFP shader reads from cache)
|
||||
if (isCachingEnabled() && pname == GL11.GL_FOG_MODE && (!isCachingEnabled() || glCtx.fogState.getFogMode() != param)) {
|
||||
beforeUncapturedStateChange();
|
||||
mod(glCtx.fogState).setFogMode(param);
|
||||
glCtx.fragmentGeneration++;
|
||||
if (GLSMHooks.FOG_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.FOG_STATE_CHANGE.post(GLSMHooks.fogStateChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static FogStateStack getFogState() {
|
||||
return ctx().fogState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getFogMode() {
|
||||
return ctx().fogMode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.ScreenCapture;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.IntegerStateStack;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MainThread;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.requireContext;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMFramebuffer {
|
||||
|
||||
private GLSMFramebuffer() {}
|
||||
|
||||
// This setting varies depending on driver, so it gets queried at runtime
|
||||
public static int DEFAULT_DRAW_BUFFER = GL11.GL_BACK;
|
||||
public static boolean framebufferCompletenessIsMeaningful() { return RENDER_BACKEND.framebufferCompletenessIsMeaningful(); }
|
||||
|
||||
static int drawFramebufferBits(GLContextState glCtx, boolean stencil) {
|
||||
final int sizePname = stencil ? GL30.GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE : GL30.GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE;
|
||||
if (glCtx.drawFramebuffer == 0) {
|
||||
return RENDER_BACKEND.getFramebufferAttachmentParameteri(GL30.GL_DRAW_FRAMEBUFFER, stencil ? GL11.GL_STENCIL : GL11.GL_DEPTH, sizePname);
|
||||
}
|
||||
final int attachment = stencil ? GL30.GL_STENCIL_ATTACHMENT : GL30.GL_DEPTH_ATTACHMENT;
|
||||
if (RENDER_BACKEND.getFramebufferAttachmentParameteri(GL30.GL_DRAW_FRAMEBUFFER, attachment, GL30.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) == GL11.GL_NONE) {
|
||||
return 0;
|
||||
}
|
||||
return RENDER_BACKEND.getFramebufferAttachmentParameteri(GL30.GL_DRAW_FRAMEBUFFER, attachment, sizePname);
|
||||
}
|
||||
|
||||
static void queryDefaultDrawBuffer() {
|
||||
DEFAULT_DRAW_BUFFER = RENDER_BACKEND.getInteger(GL11.GL_DRAW_BUFFER);
|
||||
}
|
||||
|
||||
static void armFirstClear() {
|
||||
firstClearPending = true;
|
||||
}
|
||||
|
||||
public static void glDrawBuffer(int mode) {
|
||||
rejectExitCapture();
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDrawBuffer(mode);
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!isCachingEnabled() || ctx().drawBuffer.getValue() != mode) beforeUncapturedStateChange();
|
||||
if (isCachingEnabled()) mod(ctx().drawBuffer).setValue(mode);
|
||||
RENDER_BACKEND.drawBuffer(mode);
|
||||
}
|
||||
|
||||
private static boolean firstClearPending;
|
||||
private static long firstClearBlockNanos;
|
||||
|
||||
public static void glClear(int mask) {
|
||||
rejectExitCapture();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordClear(mask);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ctx().rasterizerDiscard.isEnabled() || FeedbackManager.getRenderMode() != GL11.GL_RENDER) {
|
||||
return;
|
||||
}
|
||||
if (firstClearPending && Thread.currentThread() == MainThread && getDrawFramebuffer() == 0) {
|
||||
firstClearPending = false;
|
||||
final long start = System.nanoTime();
|
||||
RENDER_BACKEND.clear(mask);
|
||||
final long end = System.nanoTime();
|
||||
if (end - start > 0) {
|
||||
firstClearBlockNanos += end - start;
|
||||
RENDER_BACKEND.recordGate(end - start, end);
|
||||
}
|
||||
return;
|
||||
}
|
||||
RENDER_BACKEND.clear(mask);
|
||||
}
|
||||
|
||||
public static long takeFirstClearBlockNanos() {
|
||||
final long value = firstClearBlockNanos;
|
||||
firstClearBlockNanos = 0L;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, ByteBuffer pixels) {
|
||||
rejectExitCapture();
|
||||
type = GLSMTextures.remapPixelTypeForGLES(format, type);
|
||||
GLSMBuffers.suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
|
||||
GLSMBuffers.restorePixelPackBuffer();
|
||||
}
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, FloatBuffer pixels) {
|
||||
rejectExitCapture();
|
||||
type = GLSMTextures.remapPixelTypeForGLES(format, type);
|
||||
GLSMBuffers.suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
|
||||
GLSMBuffers.restorePixelPackBuffer();
|
||||
}
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, IntBuffer pixels) {
|
||||
rejectExitCapture();
|
||||
type = GLSMTextures.remapPixelTypeForGLES(format, type);
|
||||
GLSMBuffers.suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
|
||||
GLSMBuffers.restorePixelPackBuffer();
|
||||
}
|
||||
|
||||
public static void glReadBuffer(int mode) {
|
||||
rejectExitCapture();
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw DisplayListManager.unsupportedInList("glReadBuffer");
|
||||
}
|
||||
RENDER_BACKEND.readBuffer(mode);
|
||||
}
|
||||
|
||||
public static void glDrawBuffers(int buffer) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDrawBuffers(1, buffer);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
RENDER_BACKEND.drawBuffers(buffer);
|
||||
}
|
||||
|
||||
public static void glDrawBuffers(IntBuffer bufs) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDrawBuffers(bufs.remaining(), bufs);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
RENDER_BACKEND.drawBuffers(bufs);
|
||||
}
|
||||
public static boolean glIsFramebuffer(int framebuffer) { rejectExitCapture(); return RENDER_BACKEND.isFramebuffer(framebuffer); }
|
||||
public static boolean glIsRenderbuffer(int renderbuffer) { rejectExitCapture(); return RENDER_BACKEND.isRenderbuffer(renderbuffer); }
|
||||
|
||||
public static void glBindFramebuffer(int target, int framebuffer) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (target == GL30.GL_FRAMEBUFFER) {
|
||||
if (glCtx.drawFramebuffer == framebuffer && glCtx.readFramebuffer == framebuffer) return;
|
||||
if (glCtx.drawFramebuffer != framebuffer) glCtx.drawFramebufferGeneration++;
|
||||
glCtx.drawFramebuffer = framebuffer;
|
||||
glCtx.readFramebuffer = framebuffer;
|
||||
} else if (target == GL30.GL_DRAW_FRAMEBUFFER) {
|
||||
if (glCtx.drawFramebuffer == framebuffer) return;
|
||||
glCtx.drawFramebufferGeneration++;
|
||||
glCtx.drawFramebuffer = framebuffer;
|
||||
} else if (target == GL30.GL_READ_FRAMEBUFFER) {
|
||||
if (glCtx.readFramebuffer == framebuffer) return;
|
||||
glCtx.readFramebuffer = framebuffer;
|
||||
}
|
||||
RENDER_BACKEND.bindFramebuffer(target, framebuffer);
|
||||
}
|
||||
|
||||
public static void glDeleteFramebuffers(int framebuffer) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.drawFramebuffer == framebuffer) { glCtx.drawFramebuffer = 0; glCtx.drawFramebufferGeneration++; }
|
||||
if (glCtx.readFramebuffer == framebuffer) glCtx.readFramebuffer = 0;
|
||||
final int[] slots = glCtx.framebufferTextures.remove(framebuffer);
|
||||
if (slots != null) {
|
||||
for (int slot = 0; slot < slots.length; slot++) GLSMTextureLifetime.setFramebufferSlot(slots, slot, 0);
|
||||
}
|
||||
RENDER_BACKEND.deleteFramebuffers(framebuffer);
|
||||
}
|
||||
|
||||
public static void glDeleteFramebuffers(IntBuffer framebuffers) {
|
||||
for (int i = framebuffers.position(); i < framebuffers.limit(); i++) glDeleteFramebuffers(framebuffers.get(i));
|
||||
}
|
||||
|
||||
public static void glDeleteFramebuffers(int[] framebuffers) {
|
||||
for (int framebuffer : framebuffers) glDeleteFramebuffers(framebuffer);
|
||||
}
|
||||
|
||||
public static int glGenFramebuffers() {
|
||||
requireContext("glGenFramebuffers");
|
||||
return RENDER_BACKEND.genFramebuffers();
|
||||
}
|
||||
|
||||
public static int glCheckFramebufferStatus(int target) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.checkFramebufferStatus(target);
|
||||
}
|
||||
|
||||
public static int glGetFramebufferAttachmentParameteri(int target, int attachment, int pname) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getFramebufferAttachmentParameteri(target, attachment, pname);
|
||||
}
|
||||
|
||||
public static void glFramebufferTexture2D(int target, int attachment, int textarget, int texture, int level) {
|
||||
rejectExitCapture();
|
||||
if (!GLSMTextureLifetime.beginAttach(target, attachment, texture)) return;
|
||||
RENDER_BACKEND.framebufferTexture2D(target, attachment, textarget, texture, level);
|
||||
}
|
||||
|
||||
public static void glFramebufferTexture1D(int target, int attachment, int textarget, int texture, int level) {
|
||||
rejectExitCapture();
|
||||
if (!GLSMTextureLifetime.beginAttach(target, attachment, texture)) return;
|
||||
RENDER_BACKEND.framebufferTexture1D(target, attachment, textarget, texture, level);
|
||||
}
|
||||
|
||||
public static void glFramebufferTexture3D(int target, int attachment, int textarget, int texture, int level, int zoffset) {
|
||||
rejectExitCapture();
|
||||
if (!GLSMTextureLifetime.beginAttach(target, attachment, texture)) return;
|
||||
RENDER_BACKEND.framebufferTexture3D(target, attachment, textarget, texture, level, zoffset);
|
||||
}
|
||||
|
||||
public static void glFramebufferTextureLayer(int target, int attachment, int texture, int level, int layer) {
|
||||
rejectExitCapture();
|
||||
if (!GLSMTextureLifetime.beginAttach(target, attachment, texture)) return;
|
||||
RENDER_BACKEND.framebufferTextureLayer(target, attachment, texture, level, layer);
|
||||
}
|
||||
|
||||
public static void glFramebufferTexture(int target, int attachment, int texture, int level) {
|
||||
rejectExitCapture();
|
||||
if (!GLSMTextureLifetime.beginAttach(target, attachment, texture)) return;
|
||||
RENDER_BACKEND.framebufferTexture(target, attachment, texture, level);
|
||||
}
|
||||
|
||||
public static void glFramebufferTextureFace(int target, int attachment, int texture, int level, int face) {
|
||||
glFramebufferTexture2D(target, attachment, face, texture, level);
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferTexture(int framebuffer, int attachment, int texture, int level) {
|
||||
rejectExitCapture();
|
||||
if (!GLSMTextureLifetime.beginAttach(ctx(), framebuffer, attachment, texture)) return;
|
||||
RENDER_BACKEND.namedFramebufferTexture(framebuffer, attachment, texture, level);
|
||||
}
|
||||
|
||||
private static int swapDrawFramebuffer(int framebuffer) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final int previous = glCtx.drawFramebuffer;
|
||||
glCtx.drawFramebuffer = framebuffer;
|
||||
RENDER_BACKEND.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, framebuffer);
|
||||
return previous;
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferTextureLayer(int framebuffer, int attachment, int texture, int level, int layer) {
|
||||
final int previous = swapDrawFramebuffer(framebuffer);
|
||||
glFramebufferTextureLayer(GL30.GL_DRAW_FRAMEBUFFER, attachment, texture, level, layer);
|
||||
swapDrawFramebuffer(previous);
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferRenderbuffer(int framebuffer, int attachment, int renderbuffertarget, int renderbuffer) {
|
||||
final int previous = swapDrawFramebuffer(framebuffer);
|
||||
glFramebufferRenderbuffer(GL30.GL_DRAW_FRAMEBUFFER, attachment, renderbuffertarget, renderbuffer);
|
||||
swapDrawFramebuffer(previous);
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferTexture1DEXT(int framebuffer, int attachment, int textarget, int texture, int level) {
|
||||
final int previous = swapDrawFramebuffer(framebuffer);
|
||||
glFramebufferTexture1D(GL30.GL_DRAW_FRAMEBUFFER, attachment, textarget, texture, level);
|
||||
swapDrawFramebuffer(previous);
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferTexture2DEXT(int framebuffer, int attachment, int textarget, int texture, int level) {
|
||||
final int previous = swapDrawFramebuffer(framebuffer);
|
||||
glFramebufferTexture2D(GL30.GL_DRAW_FRAMEBUFFER, attachment, textarget, texture, level);
|
||||
swapDrawFramebuffer(previous);
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferTexture3DEXT(int framebuffer, int attachment, int textarget, int texture, int level, int zoffset) {
|
||||
final int previous = swapDrawFramebuffer(framebuffer);
|
||||
glFramebufferTexture3D(GL30.GL_DRAW_FRAMEBUFFER, attachment, textarget, texture, level, zoffset);
|
||||
swapDrawFramebuffer(previous);
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferTextureEXT(int framebuffer, int attachment, int texture, int level) {
|
||||
final int previous = swapDrawFramebuffer(framebuffer);
|
||||
glFramebufferTexture(GL30.GL_DRAW_FRAMEBUFFER, attachment, texture, level);
|
||||
swapDrawFramebuffer(previous);
|
||||
}
|
||||
|
||||
public static void glNamedFramebufferTextureFaceEXT(int framebuffer, int attachment, int texture, int level, int face) {
|
||||
glNamedFramebufferTexture2DEXT(framebuffer, attachment, face, texture, level);
|
||||
}
|
||||
|
||||
public static void attachTextureForReading(int attachment, int texture) {
|
||||
if (GLSMTextureLifetime.isDeferredDelete(texture)) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
GLSMTextureLifetime.trackFramebufferAttachment(glCtx, glCtx.readFramebuffer, attachment, texture);
|
||||
RENDER_BACKEND.framebufferTexture2D(GL30.GL_READ_FRAMEBUFFER, attachment, GL11.GL_TEXTURE_2D, texture, 0);
|
||||
}
|
||||
|
||||
public static int glGenRenderbuffers() {
|
||||
requireContext("glGenRenderbuffers");
|
||||
return RENDER_BACKEND.genRenderbuffers();
|
||||
}
|
||||
public static void glDeleteRenderbuffers(int renderbuffer) { rejectExitCapture(); RENDER_BACKEND.deleteRenderbuffers(renderbuffer); }
|
||||
public static void glBindRenderbuffer(int target, int renderbuffer) { rejectExitCapture(); RENDER_BACKEND.bindRenderbuffer(target, renderbuffer); }
|
||||
public static void glRenderbufferStorage(int target, int internalformat, int width, int height) { rejectExitCapture(); RENDER_BACKEND.renderbufferStorage(target, internalformat, width, height); }
|
||||
public static void glRenderbufferStorageMultisample(int target, int samples, int internalformat, int width, int height) { rejectExitCapture(); RENDER_BACKEND.renderbufferStorageMultisample(target, samples, internalformat, width, height); }
|
||||
public static void glFramebufferRenderbuffer(int target, int attachment, int renderbuffertarget, int renderbuffer) {
|
||||
rejectExitCapture();
|
||||
GLSMTextureLifetime.beginAttach(target, attachment, 0);
|
||||
RENDER_BACKEND.framebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
|
||||
}
|
||||
|
||||
public static void glBlitFramebuffer(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
|
||||
}
|
||||
|
||||
public static boolean isFramebufferEnabled() {
|
||||
return true;
|
||||
}
|
||||
public static void glReadPixels(int x, int y, int width, int height, int format, int type, long pixels) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, GLSMTextures.remapPixelTypeForGLES(format, type), pixels);
|
||||
}
|
||||
|
||||
public static ScreenCapture createScreenCapture(int width, int height) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.createScreenCapture(width, height);
|
||||
}
|
||||
|
||||
public static int getDrawFramebufferGeneration() {
|
||||
return ctx().drawFramebufferGeneration;
|
||||
}
|
||||
|
||||
public static IntegerStateStack getDrawBuffer() {
|
||||
return ctx().drawBuffer;
|
||||
}
|
||||
|
||||
public static int getDrawFramebuffer() {
|
||||
return ctx().drawFramebuffer;
|
||||
}
|
||||
|
||||
public static int getReadFramebuffer() {
|
||||
return ctx().readFramebuffer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,781 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VertexKey;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.IntegerStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.LightModelStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.LightStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.MaterialStateStack;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.LOGGER;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
|
||||
public final class GLSMLighting {
|
||||
|
||||
private GLSMLighting() {}
|
||||
|
||||
public static void glGetMaterial(int face, int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final MaterialStateStack state;
|
||||
if (face == GL11.GL_FRONT) {
|
||||
state = glCtx.frontMaterial;
|
||||
} else if (face == GL11.GL_BACK) {
|
||||
state = glCtx.backMaterial;
|
||||
} else {
|
||||
throw new RuntimeException("Invalid face parameter specified to glGetMaterial: " + face);
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL11.GL_AMBIENT -> state.ambient.get(params.position(), params);
|
||||
case GL11.GL_DIFFUSE -> state.diffuse.get(params.position(), params);
|
||||
case GL11.GL_SPECULAR -> state.specular.get(params.position(), params);
|
||||
case GL11.GL_EMISSION -> state.emission.get(params.position(), params);
|
||||
case GL11.GL_SHININESS -> params.put(params.position(), state.shininess);
|
||||
case GL11.GL_COLOR_INDEXES -> state.colorIndexes.get(params.position(), params);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void putLightingInts(FloatBuffer values, int pname, boolean material, IntBuffer params) {
|
||||
final int count = switch (pname) {
|
||||
case GL11.GL_AMBIENT, GL11.GL_DIFFUSE, GL11.GL_SPECULAR -> 4;
|
||||
case GL11.GL_EMISSION -> material ? 4 : 0;
|
||||
case GL11.GL_COLOR_INDEXES -> material ? 3 : 0;
|
||||
case GL11.GL_SHININESS -> material ? 1 : 0;
|
||||
case GL11.GL_POSITION -> material ? 0 : 4;
|
||||
case GL11.GL_SPOT_DIRECTION -> material ? 0 : 3;
|
||||
case GL11.GL_SPOT_EXPONENT, GL11.GL_SPOT_CUTOFF, GL11.GL_CONSTANT_ATTENUATION, GL11.GL_LINEAR_ATTENUATION,
|
||||
GL11.GL_QUADRATIC_ATTENUATION -> material ? 0 : 1;
|
||||
default -> 0;
|
||||
};
|
||||
final boolean color = count == 4 && pname != GL11.GL_POSITION;
|
||||
final int pos = params.position();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final float value = values.get(i);
|
||||
final int converted;
|
||||
if (color) {
|
||||
converted = LegacyQueries.floatToInt(value);
|
||||
} else if (material) {
|
||||
converted = LegacyQueries.lround(value);
|
||||
} else {
|
||||
converted = (int) value;
|
||||
}
|
||||
params.put(pos + i, converted);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glGetMaterial(int face, int pname, IntBuffer params) {
|
||||
final FloatBuffer scratch = ctx().queryScratch;
|
||||
scratch.clear();
|
||||
glGetMaterial(face, pname, scratch);
|
||||
putLightingInts(scratch, pname, true, params);
|
||||
}
|
||||
|
||||
public static void glGetLight(int light, int pname, IntBuffer params) {
|
||||
final FloatBuffer scratch = ctx().queryScratch;
|
||||
scratch.clear();
|
||||
glGetLight(light, pname, scratch);
|
||||
putLightingInts(scratch, pname, false, params);
|
||||
}
|
||||
|
||||
public static void glGetLight(int light, int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final LightStateStack state = ctx().lightDataStates[light - GL11.GL_LIGHT0];
|
||||
switch (pname) {
|
||||
case GL11.GL_AMBIENT -> state.ambient.get(params.position(), params);
|
||||
case GL11.GL_DIFFUSE -> state.diffuse.get(params.position(), params);
|
||||
case GL11.GL_SPECULAR -> state.specular.get(params.position(), params);
|
||||
case GL11.GL_POSITION -> state.position.get(params.position(), params);
|
||||
case GL11.GL_SPOT_DIRECTION -> state.spotDirection.get(params.position(), params);
|
||||
case GL11.GL_SPOT_EXPONENT -> params.put(params.position(), state.spotExponent);
|
||||
case GL11.GL_SPOT_CUTOFF -> params.put(params.position(), state.spotCutoff);
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> params.put(params.position(), state.constantAttenuation);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> params.put(params.position(), state.linearAttenuation);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> params.put(params.position(), state.quadraticAttenuation);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float i2f(int i) {return ((i - Integer.MIN_VALUE) & 0xFFFFFFFFL) / 4294967295.0F;}
|
||||
|
||||
public static void enableLighting() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_LIGHTING);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableLighting(ctx());
|
||||
}
|
||||
|
||||
static void enableLighting(GLContextState glCtx) {
|
||||
glCtx.lightingState.enable();
|
||||
}
|
||||
|
||||
public static void enableLight(int light) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_LIGHT0 + light);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableLight(ctx(), light);
|
||||
}
|
||||
|
||||
static void enableLight(GLContextState glCtx, int light) {
|
||||
if (light >= VertexKey.FFP_LIGHT_COUNT && (warnedFfpLightMask & (1 << light)) == 0 && ShaderManager.isEnabled()) {
|
||||
warnedFfpLightMask |= (1 << light);
|
||||
LOGGER.warn("GL_LIGHT{} enabled, but FFP shader emulation implements only GL_LIGHT0..{}", light, VertexKey.FFP_LIGHT_COUNT - 1, new Throwable("call site"));
|
||||
}
|
||||
glCtx.lightStates[light].enable();
|
||||
}
|
||||
|
||||
private static int warnedFfpLightMask = 0;
|
||||
|
||||
public static void enableColorMaterial() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_COLOR_MATERIAL);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableColorMaterial(ctx());
|
||||
}
|
||||
|
||||
static void enableColorMaterial(GLContextState glCtx) {
|
||||
glCtx.colorMaterial.enable();
|
||||
bakeCurrentColorIntoTrackedMaterial(glCtx);
|
||||
}
|
||||
|
||||
public static void disableColorMaterial() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_COLOR_MATERIAL);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableColorMaterial(ctx());
|
||||
}
|
||||
|
||||
static void disableColorMaterial(GLContextState glCtx) {
|
||||
bakeCurrentColorIntoTrackedMaterial(glCtx);
|
||||
glCtx.colorMaterial.disable();
|
||||
}
|
||||
|
||||
private static void bakeCurrentColorIntoTrackedMaterial(GLContextState glCtx) {
|
||||
glCtx.exitCapture.requireMaterialBakeInputs();
|
||||
final float r = glCtx.color.getRed();
|
||||
final float g = glCtx.color.getGreen();
|
||||
final float b = glCtx.color.getBlue();
|
||||
final float a = glCtx.color.getAlpha();
|
||||
final int face = glCtx.colorMaterialFace.getValue();
|
||||
final int param = glCtx.colorMaterialParameter.getValue();
|
||||
if (face == GL11.GL_FRONT || face == GL11.GL_FRONT_AND_BACK) {
|
||||
bakeMaterialColor(glCtx, glCtx.frontMaterial, param, r, g, b, a);
|
||||
}
|
||||
if (face == GL11.GL_BACK || face == GL11.GL_FRONT_AND_BACK) {
|
||||
bakeMaterialColor(glCtx, glCtx.backMaterial, param, r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean materialVectorDiffers(Vector4f vec, float r, float g, float b, float a) {
|
||||
return vec.x != r || vec.y != g || vec.z != b || vec.w != a;
|
||||
}
|
||||
|
||||
private static void bakeMaterialColor(GLContextState glCtx, MaterialStateStack material, int param, float r, float g, float b, float a) {
|
||||
glCtx.exitCapture.material(material.face, param);
|
||||
final boolean changed = switch (param) {
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> materialVectorDiffers(material.ambient, r, g, b, a) || materialVectorDiffers(material.diffuse, r, g, b, a);
|
||||
case GL11.GL_AMBIENT -> materialVectorDiffers(material.ambient, r, g, b, a);
|
||||
case GL11.GL_DIFFUSE -> materialVectorDiffers(material.diffuse, r, g, b, a);
|
||||
case GL11.GL_SPECULAR -> materialVectorDiffers(material.specular, r, g, b, a);
|
||||
case GL11.GL_EMISSION -> materialVectorDiffers(material.emission, r, g, b, a);
|
||||
default -> false;
|
||||
};
|
||||
if (!changed) return;
|
||||
mod(material);
|
||||
switch (param) {
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
material.ambient.set(r, g, b, a);
|
||||
material.diffuse.set(r, g, b, a);
|
||||
}
|
||||
case GL11.GL_AMBIENT -> material.ambient.set(r, g, b, a);
|
||||
case GL11.GL_DIFFUSE -> material.diffuse.set(r, g, b, a);
|
||||
case GL11.GL_SPECULAR -> material.specular.set(r, g, b, a);
|
||||
case GL11.GL_EMISSION -> material.emission.set(r, g, b, a);
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
public static void disableLighting() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_LIGHTING);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableLighting(ctx());
|
||||
}
|
||||
|
||||
static void disableLighting(GLContextState glCtx) {
|
||||
glCtx.lightingState.disable();
|
||||
}
|
||||
|
||||
public static void disableLight(int light) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_LIGHT0 + light);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableLight(ctx(), light);
|
||||
}
|
||||
|
||||
static void disableLight(GLContextState glCtx, int light) {
|
||||
glCtx.lightStates[light].disable();
|
||||
}
|
||||
|
||||
public static void enableRescaleNormal() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL12.GL_RESCALE_NORMAL);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableRescaleNormal(ctx());
|
||||
}
|
||||
|
||||
static void enableRescaleNormal(GLContextState glCtx) {
|
||||
glCtx.rescaleNormalState.enable();
|
||||
}
|
||||
|
||||
public static void disableRescaleNormal() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL12.GL_RESCALE_NORMAL);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableRescaleNormal(ctx());
|
||||
}
|
||||
|
||||
static void disableRescaleNormal(GLContextState glCtx) {
|
||||
glCtx.rescaleNormalState.disable();
|
||||
}
|
||||
|
||||
private static boolean glMaterialFront(int pname, FloatBuffer params) {
|
||||
final GLContextState glCtx = ctx();
|
||||
mod(glCtx.frontMaterial);
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> glCtx.frontMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> glCtx.frontMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> glCtx.frontMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> glCtx.frontMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> glCtx.frontMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
final boolean a = glCtx.frontMaterial.setAmbient(params);
|
||||
final boolean d = glCtx.frontMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> glCtx.frontMaterial.setColorIndexes(params);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean glMaterialBack(int pname, FloatBuffer params) {
|
||||
final GLContextState glCtx = ctx();
|
||||
mod(glCtx.backMaterial);
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> glCtx.backMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> glCtx.backMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> glCtx.backMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> glCtx.backMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> glCtx.backMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
final boolean a = glCtx.backMaterial.setAmbient(params);
|
||||
final boolean d = glCtx.backMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> glCtx.backMaterial.setColorIndexes(params);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean glMaterialFront(int pname, IntBuffer params) {
|
||||
final GLContextState glCtx = ctx();
|
||||
mod(glCtx.frontMaterial);
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> glCtx.frontMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> glCtx.frontMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> glCtx.frontMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> glCtx.frontMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> glCtx.frontMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
final boolean a = glCtx.frontMaterial.setAmbient(params);
|
||||
final boolean d = glCtx.frontMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> glCtx.frontMaterial.setColorIndexes(params);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean glMaterialBack(int pname, IntBuffer params) {
|
||||
final GLContextState glCtx = ctx();
|
||||
mod(glCtx.backMaterial);
|
||||
return switch (pname) {
|
||||
case GL11.GL_AMBIENT -> glCtx.backMaterial.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> glCtx.backMaterial.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> glCtx.backMaterial.setSpecular(params);
|
||||
case GL11.GL_EMISSION -> glCtx.backMaterial.setEmission(params);
|
||||
case GL11.GL_SHININESS -> glCtx.backMaterial.setShininess(params);
|
||||
case GL11.GL_AMBIENT_AND_DIFFUSE -> {
|
||||
final boolean a = glCtx.backMaterial.setAmbient(params);
|
||||
final boolean d = glCtx.backMaterial.setDiffuse(params);
|
||||
yield a || d;
|
||||
}
|
||||
case GL11.GL_COLOR_INDEXES -> glCtx.backMaterial.setColorIndexes(params);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public static void glMaterial(int face, int pname, FloatBuffer params) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.material(face, pname);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordMaterial(face, pname, params);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
boolean changed = false;
|
||||
if (face == GL11.GL_FRONT) {
|
||||
changed = glMaterialFront(pname, params);
|
||||
} else if (face == GL11.GL_BACK) {
|
||||
changed = glMaterialBack(pname, params);
|
||||
} else if (face == GL11.GL_FRONT_AND_BACK) {
|
||||
final boolean f = glMaterialFront(pname, params);
|
||||
final boolean b = glMaterialBack(pname, params);
|
||||
changed = f || b;
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported face value for glMaterial: " + face);
|
||||
}
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glMaterial(int face, int pname, IntBuffer params) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.material(face, pname);
|
||||
// For IntBuffer version, we need to convert to float for recording
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
// Convert int params to float for recording
|
||||
final float[] floatParams = new float[params.remaining()];
|
||||
params.mark();
|
||||
for (int i = 0; i < floatParams.length; i++) {
|
||||
floatParams[i] = i2f(params.get());
|
||||
}
|
||||
params.reset();
|
||||
DisplayListManager.recordMaterial(face, pname, FloatBuffer.wrap(floatParams));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
boolean changed = false;
|
||||
if (face == GL11.GL_FRONT) {
|
||||
changed = glMaterialFront(pname, params);
|
||||
} else if (face == GL11.GL_BACK) {
|
||||
changed = glMaterialBack(pname, params);
|
||||
} else if (face == GL11.GL_FRONT_AND_BACK) {
|
||||
final boolean f = glMaterialFront(pname, params);
|
||||
final boolean b = glMaterialBack(pname, params);
|
||||
changed = f || b;
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported face value for glMaterial: " + face);
|
||||
}
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glMaterialf(int face, int pname, float val) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordMaterialf(face, pname, val);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (pname != GL11.GL_SHININESS) {
|
||||
// it is only valid to call glMaterialf for the GL_SHININESS parameter
|
||||
return;
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
if (face == GL11.GL_FRONT) {
|
||||
mod(glCtx.frontMaterial);
|
||||
changed = glCtx.frontMaterial.setShininess(val);
|
||||
} else if (face == GL11.GL_BACK) {
|
||||
mod(glCtx.backMaterial);
|
||||
changed = glCtx.backMaterial.setShininess(val);
|
||||
} else if (face == GL11.GL_FRONT_AND_BACK) {
|
||||
mod(glCtx.frontMaterial);
|
||||
mod(glCtx.backMaterial);
|
||||
final boolean f = glCtx.frontMaterial.setShininess(val);
|
||||
final boolean b = glCtx.backMaterial.setShininess(val);
|
||||
changed = f || b;
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported face value for glMaterial: " + face);
|
||||
}
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glMateriali(int face, int pname, int val) {
|
||||
// This will end up no-opping if pname != GL_SHININESS, it is invalid to call this with another pname
|
||||
// Command recording happens in glMaterialf
|
||||
glMaterialf(face, pname, (float) val);
|
||||
}
|
||||
|
||||
public static void glLight(int light, int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLight(light, pname, params);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = glCtx.lightDataStates[light - GL11.GL_LIGHT0];
|
||||
mod(lightState);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_AMBIENT -> lightState.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> lightState.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> lightState.setSpecular(params);
|
||||
case GL11.GL_POSITION -> lightState.setPosition(params);
|
||||
case GL11.GL_SPOT_DIRECTION -> lightState.setSpotDirection(params);
|
||||
case GL11.GL_SPOT_EXPONENT -> lightState.setSpotExponent(params);
|
||||
case GL11.GL_SPOT_CUTOFF -> lightState.setSpotCutoff(params);
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(params);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(params);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(params);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLight(int light, int pname, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
// For IntBuffer version, we need to convert to float for recording
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
// Convert int params to float for recording
|
||||
final float[] floatParams = new float[params.remaining()];
|
||||
params.mark();
|
||||
for (int i = 0; i < floatParams.length; i++) {
|
||||
floatParams[i] = i2f(params.get());
|
||||
}
|
||||
params.reset();
|
||||
DisplayListManager.recordLight(light, pname, FloatBuffer.wrap(floatParams));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = glCtx.lightDataStates[light - GL11.GL_LIGHT0];
|
||||
mod(lightState);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_AMBIENT -> lightState.setAmbient(params);
|
||||
case GL11.GL_DIFFUSE -> lightState.setDiffuse(params);
|
||||
case GL11.GL_SPECULAR -> lightState.setSpecular(params);
|
||||
case GL11.GL_POSITION -> lightState.setPosition(params);
|
||||
case GL11.GL_SPOT_DIRECTION -> lightState.setSpotDirection(params);
|
||||
case GL11.GL_SPOT_EXPONENT -> lightState.setSpotExponent(params);
|
||||
case GL11.GL_SPOT_CUTOFF -> lightState.setSpotCutoff(params);
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(params);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(params);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(params);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightf(int light, int pname, float param) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLightf(light, pname, param);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = glCtx.lightDataStates[light - GL11.GL_LIGHT0];
|
||||
mod(lightState);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_SPOT_EXPONENT -> lightState.setSpotExponent(param);
|
||||
case GL11.GL_SPOT_CUTOFF -> lightState.setSpotCutoff(param);
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(param);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(param);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(param);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLighti(int light, int pname, int param) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLighti(light, pname, param);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final LightStateStack lightState = glCtx.lightDataStates[light - GL11.GL_LIGHT0];
|
||||
mod(lightState);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_SPOT_EXPONENT -> lightState.setSpotExponent(param);
|
||||
case GL11.GL_SPOT_CUTOFF -> lightState.setSpotCutoff(param);
|
||||
case GL11.GL_CONSTANT_ATTENUATION -> lightState.setConstantAttenuation(param);
|
||||
case GL11.GL_LINEAR_ATTENUATION -> lightState.setLinearAttenuation(param);
|
||||
case GL11.GL_QUADRATIC_ATTENUATION -> lightState.setQuadraticAttenuation(param);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightModel(int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLightModel(pname, params);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mod(glCtx.lightModel);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_LIGHT_MODEL_AMBIENT -> glCtx.lightModel.setAmbient(params);
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> glCtx.lightModel.setLocalViewer(params);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> glCtx.lightModel.setTwoSide(params);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightModel(int pname, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
// For IntBuffer version, we need to convert to float for recording
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
// Convert int params to float for recording
|
||||
final float[] floatParams = new float[params.remaining()];
|
||||
params.mark();
|
||||
for (int i = 0; i < floatParams.length; i++) {
|
||||
floatParams[i] = i2f(params.get());
|
||||
}
|
||||
params.reset();
|
||||
DisplayListManager.recordLightModel(pname, FloatBuffer.wrap(floatParams));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mod(glCtx.lightModel);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_LIGHT_MODEL_AMBIENT -> glCtx.lightModel.setAmbient(params);
|
||||
case GL12.GL_LIGHT_MODEL_COLOR_CONTROL -> glCtx.lightModel.setColorControl(params);
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> glCtx.lightModel.setLocalViewer(params);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> glCtx.lightModel.setTwoSide(params);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
|
||||
public static void glLightModelf(int pname, float param) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLightModelf(pname, param);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCachingEnabled()) {
|
||||
mod(glCtx.lightModel);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> glCtx.lightModel.setLocalViewer(param);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> glCtx.lightModel.setTwoSide(param);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLightModeli(int pname, int param) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLightModeli(pname, param);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isCachingEnabled()) {
|
||||
mod(glCtx.lightModel);
|
||||
final boolean changed = switch (pname) {
|
||||
case GL12.GL_LIGHT_MODEL_COLOR_CONTROL -> glCtx.lightModel.setColorControl(param);
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> glCtx.lightModel.setLocalViewer(param);
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> glCtx.lightModel.setTwoSide(param);
|
||||
default -> false;
|
||||
};
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glColorMaterial(int face, int mode) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.COLOR_MATERIAL_SETTINGS);
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
DisplayListManager.recordColorMaterial(face, mode);
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.colorMaterialFace.getValue() != face || glCtx.colorMaterialParameter.getValue() != mode) {
|
||||
mod(glCtx.colorMaterialFace).setValue(face);
|
||||
mod(glCtx.colorMaterialParameter).setValue(mode);
|
||||
glCtx.lightingGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getLightingGeneration() {
|
||||
return ctx().lightingGeneration;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getLightingState() {
|
||||
return ctx().lightingState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getRescaleNormalState() {
|
||||
return ctx().rescaleNormalState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getNormalizeState() {
|
||||
return ctx().normalizeState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack[] getLightStates() {
|
||||
return ctx().lightStates;
|
||||
}
|
||||
|
||||
public static LightStateStack[] getLightDataStates() {
|
||||
return ctx().lightDataStates;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getColorMaterial() {
|
||||
return ctx().colorMaterial;
|
||||
}
|
||||
|
||||
public static IntegerStateStack getColorMaterialFace() {
|
||||
return ctx().colorMaterialFace;
|
||||
}
|
||||
|
||||
public static IntegerStateStack getColorMaterialParameter() {
|
||||
return ctx().colorMaterialParameter;
|
||||
}
|
||||
|
||||
public static LightModelStateStack getLightModel() {
|
||||
return ctx().lightModel;
|
||||
}
|
||||
|
||||
public static MaterialStateStack getFrontMaterial() {
|
||||
return ctx().frontMaterial;
|
||||
}
|
||||
|
||||
public static MaterialStateStack getBackMaterial() {
|
||||
return ctx().backMaterial;
|
||||
}
|
||||
|
||||
public static void captureLighting(LightingSnapshot out) {
|
||||
final GLContextState glCtx = ctx();
|
||||
for (int i = 0; i < out.lights.length; i++) {
|
||||
out.lightEnabled[i] = glCtx.lightStates[i].isEnabled();
|
||||
out.lights[i].set(glCtx.lightDataStates[i]);
|
||||
}
|
||||
out.lightModel.set(glCtx.lightModel);
|
||||
out.frontMaterial.set(glCtx.frontMaterial);
|
||||
out.backMaterial.set(glCtx.backMaterial);
|
||||
out.colorMaterial = glCtx.colorMaterial.isEnabled();
|
||||
out.colorMaterialFace = glCtx.colorMaterialFace.getValue();
|
||||
out.colorMaterialParameter = glCtx.colorMaterialParameter.getValue();
|
||||
out.normalize = glCtx.normalizeState.isEnabled();
|
||||
out.rescaleNormal = glCtx.rescaleNormalState.isEnabled();
|
||||
}
|
||||
|
||||
public static void applyLighting(LightingSnapshot in) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
boolean changed = false;
|
||||
for (int i = 0; i < in.lights.length; i++) {
|
||||
glCtx.lightStates[i].setEnabled(in.lightEnabled[i]);
|
||||
if (!glCtx.lightDataStates[i].sameAs(in.lights[i])) {
|
||||
mod(glCtx.lightDataStates[i]).set(in.lights[i]);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (!glCtx.lightModel.sameAs(in.lightModel)) {
|
||||
mod(glCtx.lightModel).set(in.lightModel);
|
||||
changed = true;
|
||||
}
|
||||
if (!glCtx.frontMaterial.sameAs(in.frontMaterial)) {
|
||||
mod(glCtx.frontMaterial).set(in.frontMaterial);
|
||||
changed = true;
|
||||
}
|
||||
if (!glCtx.backMaterial.sameAs(in.backMaterial)) {
|
||||
mod(glCtx.backMaterial).set(in.backMaterial);
|
||||
changed = true;
|
||||
}
|
||||
if (glCtx.colorMaterialFace.getValue() != in.colorMaterialFace || glCtx.colorMaterialParameter.getValue() != in.colorMaterialParameter) {
|
||||
mod(glCtx.colorMaterialFace).setValue(in.colorMaterialFace);
|
||||
mod(glCtx.colorMaterialParameter).setValue(in.colorMaterialParameter);
|
||||
changed = true;
|
||||
}
|
||||
// Direct set: glEnable(GL_COLOR_MATERIAL) would bake the current color over the captured material.
|
||||
glCtx.colorMaterial.setEnabled(in.colorMaterial);
|
||||
glCtx.normalizeState.setEnabled(in.normalize);
|
||||
glCtx.rescaleNormalState.setEnabled(in.rescaleNormal);
|
||||
if (changed) glCtx.lightingGeneration++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.MatrixModeStack;
|
||||
import lombok.SneakyThrows;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fStack;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.util.glu.GLU;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.LOGGER;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.initConfig;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
|
||||
public final class GLSMMatrices {
|
||||
|
||||
private GLSMMatrices() {}
|
||||
|
||||
private static void beforeMatrixChange(GLContextState c) {
|
||||
beforeMatrixChange(c, false);
|
||||
}
|
||||
|
||||
private static void beforeMatrixChange(GLContextState c, boolean absolute) {
|
||||
c.exitCapture.matrixChange(absolute);
|
||||
if (isUncapturedMatrix(c)) beforeUncapturedStateChange();
|
||||
}
|
||||
|
||||
private static boolean isUncapturedMatrix(GLContextState c) {
|
||||
final int mode = c.matrixMode.getMode();
|
||||
return mode == GL11.GL_PROJECTION || (mode == GL11.GL_TEXTURE && c.activeTextureUnit.getValue() != 0);
|
||||
}
|
||||
|
||||
private static final MethodHandle MAT4_STACK_CURR_DEPTH;
|
||||
|
||||
static {
|
||||
try {
|
||||
final Field curr = Matrix4fStack.class.getDeclaredField("curr");
|
||||
curr.setAccessible(true);
|
||||
MAT4_STACK_CURR_DEPTH = MethodHandles.lookup().unreflectGetter(curr);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static int getMatrixStackDepth(Matrix4fStack stack) {
|
||||
// JOML's curr is 0-based (0 = no pushes), but OpenGL starts at 1 (base matrix counts)
|
||||
return (int) MAT4_STACK_CURR_DEPTH.invokeExact(stack) + 1;
|
||||
}
|
||||
|
||||
public static void glMatrixMode(int mode) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.MATRIX_MODE);
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
DisplayListManager.recordMatrixMode(mode);
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mod(glCtx.matrixMode).setMode(mode);
|
||||
}
|
||||
|
||||
public static void glLoadMatrix(FloatBuffer m) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx, true);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
final Matrix4f matrix = new Matrix4f().set(m);
|
||||
m.rewind();
|
||||
DisplayListManager.recordLoadMatrix(matrix);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).set(m);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLoadMatrix(DoubleBuffer m) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx, true);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
// Convert double buffer to float buffer for recording
|
||||
glCtx.conversionMatrix4d.set(m);
|
||||
m.rewind();
|
||||
final Matrix4f floatMatrix = new Matrix4f();
|
||||
floatMatrix.set(glCtx.conversionMatrix4d);
|
||||
DisplayListManager.recordLoadMatrix(floatMatrix);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
glCtx.conversionMatrix4d.set(m);
|
||||
matrixStack(glCtx).set(glCtx.conversionMatrix4d);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setModelViewMatrix(Matrix4fc m) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.matrixChange(GL11.GL_MODELVIEW, 0, true);
|
||||
if (isCachingEnabled()) {
|
||||
glCtx.modelViewMatrix.set(m);
|
||||
glCtx.mvGeneration++;
|
||||
glCtx.mvLinearGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setTextureMatrix(int unit, Matrix4fc m) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.matrixChange(GL11.GL_TEXTURE, unit, true);
|
||||
if (unit != 0) beforeUncapturedStateChange();
|
||||
if (isCachingEnabled()) {
|
||||
glCtx.textures.getTextureUnitMatrix(unit).set(m);
|
||||
glCtx.texMatrixGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setProjectionMatrix(Matrix4fc m) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (isCachingEnabled()) {
|
||||
glCtx.projectionMatrix.set(m);
|
||||
glCtx.projGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static Matrix4fStack getMatrixStack() {
|
||||
return matrixStack(ctx());
|
||||
}
|
||||
|
||||
private static Matrix4fStack matrixStack(GLContextState glCtx) {
|
||||
switch (glCtx.matrixMode.getMode()) {
|
||||
case GL11.GL_MODELVIEW -> {
|
||||
return glCtx.modelViewMatrix;
|
||||
}
|
||||
case GL11.GL_PROJECTION -> {
|
||||
return glCtx.projectionMatrix;
|
||||
}
|
||||
case GL11.GL_TEXTURE -> {
|
||||
return glCtx.textures.getTextureUnitMatrix(glCtx.activeTextureUnit.getValue());
|
||||
}
|
||||
default -> throw new IllegalStateException("Unknown matrix mode: " + glCtx.matrixMode.getMode());
|
||||
}
|
||||
}
|
||||
|
||||
/** Bump the generation counter for the currently active matrix mode. */
|
||||
private static void bumpMatrixGeneration(GLContextState glCtx) {
|
||||
bumpMatrixGeneration(glCtx, true);
|
||||
}
|
||||
|
||||
private static void bumpMatrixGeneration(GLContextState glCtx, boolean linearChanged) {
|
||||
switch (glCtx.matrixMode.getMode()) {
|
||||
case GL11.GL_MODELVIEW -> {
|
||||
glCtx.mvGeneration++;
|
||||
if (linearChanged) glCtx.mvLinearGeneration++;
|
||||
}
|
||||
case GL11.GL_PROJECTION -> glCtx.projGeneration++;
|
||||
case GL11.GL_TEXTURE -> glCtx.texMatrixGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLoadIdentity() {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx, true);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLoadIdentity();
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).identity();
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glTranslatef(float x, float y, float z) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.applyMatrixTranslation(x, y, z);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).translate(x, y, z);
|
||||
bumpMatrixGeneration(glCtx, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glTranslated(double x, double y, double z) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.applyMatrixTranslation((float) x, (float) y, (float) z);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).translate((float) x, (float) y, (float) z);
|
||||
bumpMatrixGeneration(glCtx, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glScalef(float x, float y, float z) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.applyMatrixScale(x, y, z);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).scale(x, y, z);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glScaled(double x, double y, double z) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.applyMatrixScale((float) x, (float) y, (float) z);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).scale((float) x, (float) y, (float) z);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glMultMatrix(FloatBuffer floatBuffer) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
glCtx.multMatrix.set(floatBuffer);
|
||||
final int currentMode = glCtx.matrixMode.getMode();
|
||||
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.updateRelativeTransform(glCtx.multMatrix);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).mul(glCtx.multMatrix);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyMultMatrix(Matrix4f multMatrix) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).mul(multMatrix);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glMultMatrix(DoubleBuffer matrix) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
glCtx.conversionMatrix4d.set(matrix);
|
||||
glCtx.conversionMatrix4f.set(glCtx.conversionMatrix4d);
|
||||
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.updateRelativeTransform(glCtx.conversionMatrix4f);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).mul(glCtx.conversionMatrix4f);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glRotatef(float angle, float x, float y, float z) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
final float lenSq = x * x + y * y + z * z;
|
||||
if (lenSq == 0.0f) return;
|
||||
|
||||
// Fast way to normalize rotation
|
||||
final float scalar = 1.0f / (float) Math.sqrt(lenSq);
|
||||
x *= scalar;
|
||||
y *= scalar;
|
||||
z *= scalar;
|
||||
// Convert deg to rad
|
||||
angle = (float) Math.toRadians(angle);
|
||||
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.applyMatrixRotation(angle, x, y, z);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).rotate(angle, x, y, z);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glRotated(double angle, double x, double y, double z) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
final double lenSq = x * x + y * y + z * z;
|
||||
if (lenSq == 0.0) return;
|
||||
|
||||
// Fast way to normalize rotation
|
||||
final double scalar = 1.0 / Math.sqrt(lenSq);
|
||||
x *= scalar;
|
||||
y *= scalar;
|
||||
z *= scalar;
|
||||
// Convert deg to rad
|
||||
angle = Math.toRadians(angle);
|
||||
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.applyMatrixRotation((float) angle, (float) x, (float) y, (float) z);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).rotate((float) angle, (float) x, (float) y, (float) z);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glOrtho(double left, double right, double bottom, double top, double zNear, double zFar) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.updateRelativeTransformOrtho(left, right, bottom, top, zNear, zFar);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).ortho((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glFrustum(double left, double right, double bottom, double top, double zNear, double zFar) {
|
||||
final GLContextState glCtx = ctx();
|
||||
beforeMatrixChange(glCtx);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.updateRelativeTransformFrustum(left, right, bottom, top, zNear, zFar);
|
||||
return;
|
||||
}
|
||||
if (isCachingEnabled()) {
|
||||
matrixStack(glCtx).frustum((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar);
|
||||
bumpMatrixGeneration(glCtx);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glPushMatrix() {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.pushMatrix();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordPushMatrix(); // Handles flush + relativeTransform stack
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Only track stack on main thread (splash thread has separate GL context)
|
||||
if (isCachingEnabled()) {
|
||||
try {
|
||||
matrixStack(glCtx).pushMatrix();
|
||||
} catch (IllegalStateException ignored) {
|
||||
glCtx.exitCapture.reject();
|
||||
if (initConfig != null && initConfig.isLwjglDebug()) LOGGER.warn("Matrix stack overflow ", new Throwable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glPopMatrix() {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.popMatrix();
|
||||
if (isUncapturedMatrix(glCtx)) beforeUncapturedStateChange();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordPopMatrix(); // Handles flush + relativeTransform stack + lastRecordedTransform sync
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Only track stack on main thread (splash thread has separate GL context)
|
||||
if (isCachingEnabled()) {
|
||||
try {
|
||||
matrixStack(glCtx).popMatrix();
|
||||
bumpMatrixGeneration(glCtx);
|
||||
} catch (IllegalStateException ignored) {
|
||||
glCtx.exitCapture.reject();
|
||||
if (initConfig != null && initConfig.isLwjglDebug()) LOGGER.warn("Matrix stack underflow ", new Throwable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void gluPerspective(float fovy, float aspect, float zNear, float zFar) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.gluMatrix.identity().perspective((float) Math.toRadians(fovy), aspect, zNear, zFar);
|
||||
glCtx.gluMatrix.get(0, glCtx.gluBuffer);
|
||||
glMultMatrix(glCtx.gluBuffer);
|
||||
}
|
||||
|
||||
public static void gluLookAt(float eyex, float eyey, float eyez, float centerx, float centery, float centerz, float upx, float upy, float upz) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.gluMatrix.identity().lookAt(eyex, eyey, eyez, centerx, centery, centerz, upx, upy, upz);
|
||||
glCtx.gluMatrix.get(0, glCtx.gluBuffer);
|
||||
glMultMatrix(glCtx.gluBuffer);
|
||||
}
|
||||
|
||||
public static void gluOrtho2D(float left, float right, float bottom, float top) {
|
||||
glOrtho(left, right, bottom, top, -1.0, 1.0);
|
||||
}
|
||||
|
||||
public static void gluPickMatrix(float x, float y, float deltaX, float deltaY, IntBuffer viewport) {
|
||||
rejectExitCapture();
|
||||
if (deltaX <= 0 || deltaY <= 0) return;
|
||||
glTranslatef(
|
||||
(viewport.get(viewport.position() + 2) - 2 * (x - viewport.get(viewport.position() + 0))) / deltaX,
|
||||
(viewport.get(viewport.position() + 3) - 2 * (y - viewport.get(viewport.position() + 1))) / deltaY,
|
||||
0);
|
||||
glScalef(viewport.get(viewport.position() + 2) / deltaX, viewport.get(viewport.position() + 3) / deltaY, 1.0f);
|
||||
}
|
||||
|
||||
public static int gluBuild2DMipmaps(int target, int components, int width, int height, int format, int type, ByteBuffer data) {
|
||||
if (width < 1 || height < 1) return GLU.GLU_INVALID_VALUE;
|
||||
GLSMTextures.glTexImage2D(target, 0, components, width, height, 0, format, type, data);
|
||||
GLSMTextures.glGenerateMipmap(target);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static String gluErrorString(int errorCode) {
|
||||
return switch (errorCode) {
|
||||
case GLU.GLU_INVALID_ENUM -> "Invalid enum (glu)";
|
||||
case GLU.GLU_INVALID_VALUE -> "Invalid value (glu)";
|
||||
case GLU.GLU_OUT_OF_MEMORY -> "Out of memory (glu)";
|
||||
case GL11.GL_NO_ERROR -> "No error";
|
||||
case GL11.GL_INVALID_ENUM -> "Invalid enum";
|
||||
case GL11.GL_INVALID_VALUE -> "Invalid value";
|
||||
case GL11.GL_INVALID_OPERATION -> "Invalid operation";
|
||||
case GL11.GL_OUT_OF_MEMORY -> "Out of memory";
|
||||
default -> "Unknown error: " + errorCode;
|
||||
};
|
||||
}
|
||||
|
||||
public static boolean gluUnProject(float winx, float winy, float winz, FloatBuffer modelMatrix, FloatBuffer projMatrix, IntBuffer viewport, FloatBuffer obj_pos) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.gluMatrix.set(projMatrix).mul(glCtx.gluMatrix2.set(modelMatrix));
|
||||
if (Math.abs(glCtx.gluMatrix.determinant()) < 1.0e-10f) return false;
|
||||
glCtx.gluMatrix.invert(glCtx.gluMatrix);
|
||||
|
||||
float ndcX = (winx - viewport.get(viewport.position())) / viewport.get(viewport.position() + 2) * 2.0f - 1.0f;
|
||||
float ndcY = (winy - viewport.get(viewport.position() + 1)) / viewport.get(viewport.position() + 3) * 2.0f - 1.0f;
|
||||
float ndcZ = winz * 2.0f - 1.0f;
|
||||
|
||||
glCtx.gluVec4.set(ndcX, ndcY, ndcZ, 1.0f);
|
||||
glCtx.gluMatrix.transform(glCtx.gluVec4);
|
||||
if (glCtx.gluVec4.w == 0.0f) return false;
|
||||
|
||||
float invW = 1.0f / glCtx.gluVec4.w;
|
||||
obj_pos.put(obj_pos.position(), glCtx.gluVec4.x * invW);
|
||||
obj_pos.put(obj_pos.position() + 1, glCtx.gluVec4.y * invW);
|
||||
obj_pos.put(obj_pos.position() + 2, glCtx.gluVec4.z * invW);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int getMvGeneration() {
|
||||
return ctx().mvGeneration;
|
||||
}
|
||||
|
||||
public static int getMvLinearGeneration() {
|
||||
return ctx().mvLinearGeneration;
|
||||
}
|
||||
|
||||
public static int getProjGeneration() {
|
||||
return ctx().projGeneration;
|
||||
}
|
||||
|
||||
public static int getTexMatrixGeneration() {
|
||||
return ctx().texMatrixGeneration;
|
||||
}
|
||||
|
||||
public static MatrixModeStack getMatrixMode() {
|
||||
return ctx().matrixMode;
|
||||
}
|
||||
|
||||
public static Matrix4fStack getModelViewMatrix() {
|
||||
return ctx().modelViewMatrix;
|
||||
}
|
||||
|
||||
public static Matrix4fStack getProjectionMatrix() {
|
||||
return ctx().projectionMatrix;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,613 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.Pointer;
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.Instancing;
|
||||
import com.gtnewhorizons.angelica.glsm.profiling.Tracy;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
import com.gtnewhorizons.angelica.glsm.shader.ProgramBinaryCache;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.IntegerStateStack;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import lombok.Getter;
|
||||
import org.lwjgl.opengl.ARBShaderObjects;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.KHRDebug;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.LOGGER;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.initConfig;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.requireContext;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.warnOnce;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMPrograms {
|
||||
|
||||
private GLSMPrograms() {}
|
||||
|
||||
public static long programSwitches;
|
||||
|
||||
private static final String TEXTURE = "texture";
|
||||
private static final String TEXTURE_RENAMED = "gtexture";
|
||||
public static void setFfpInstancing(Instancing mode) {
|
||||
ctx().ffpInstancing = mode;
|
||||
}
|
||||
|
||||
public static void glUseProgram(int program) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordUseProgram(program);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
final ShaderManager ffp = glCtx.ffp;
|
||||
if (program == 0 && ffp.isEnabled()) {
|
||||
final int prev = glCtx.activeProgram;
|
||||
final boolean changed = prev != 0;
|
||||
if (changed) glCtx.programGeneration++;
|
||||
glCtx.activeProgram = 0; // Track that FFP was requested
|
||||
if (changed && GLSMHooks.PROGRAM_CHANGE.hasListeners()) {
|
||||
GLSMHooks.programChangeEvent.previousProgram = prev;
|
||||
GLSMHooks.programChangeEvent.newProgram = 0;
|
||||
GLSMHooks.programChangeEvent.postBind = false;
|
||||
GLSMHooks.PROGRAM_CHANGE.post(GLSMHooks.programChangeEvent);
|
||||
}
|
||||
ffp.activate();
|
||||
if (changed && GLSMHooks.PROGRAM_CHANGE.hasListeners()) {
|
||||
GLSMHooks.programChangeEvent.previousProgram = prev;
|
||||
GLSMHooks.programChangeEvent.newProgram = 0;
|
||||
GLSMHooks.programChangeEvent.postBind = true;
|
||||
GLSMHooks.PROGRAM_CHANGE.post(GLSMHooks.programChangeEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-zero program or FFP emulation not enabled
|
||||
if (program == 0) {
|
||||
warnOnce("useprogram-zero-ffp-disabled",
|
||||
"[FFP] glUseProgram(0) reached the driver because emulation is disabled");
|
||||
}
|
||||
if (ffp.isActive()) {
|
||||
ffp.deactivate();
|
||||
}
|
||||
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || program != glCtx.activeProgram) {
|
||||
if (Tracy.ENABLED) programSwitches++;
|
||||
glCtx.programGeneration++;
|
||||
final int prev = glCtx.activeProgram;
|
||||
glCtx.activeProgram = program;
|
||||
if (GLSMHooks.PROGRAM_CHANGE.hasListeners()) {
|
||||
GLSMHooks.programChangeEvent.previousProgram = prev;
|
||||
GLSMHooks.programChangeEvent.newProgram = program;
|
||||
GLSMHooks.programChangeEvent.postBind = false;
|
||||
GLSMHooks.PROGRAM_CHANGE.post(GLSMHooks.programChangeEvent);
|
||||
}
|
||||
if (initConfig != null && initConfig.isLwjglDebug()) {
|
||||
final String programName = GLDebug.getObjectLabel(KHRDebug.GL_PROGRAM, program);
|
||||
GLDebug.debugMessage("Activating Program - " + program + ":" + programName);
|
||||
}
|
||||
RENDER_BACKEND.useProgram(program);
|
||||
if (GLSMHooks.PROGRAM_CHANGE.hasListeners()) {
|
||||
GLSMHooks.programChangeEvent.previousProgram = prev;
|
||||
GLSMHooks.programChangeEvent.newProgram = program;
|
||||
GLSMHooks.programChangeEvent.postBind = true;
|
||||
GLSMHooks.PROGRAM_CHANGE.post(GLSMHooks.programChangeEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glShaderSource(int shader, CharSequence source) {
|
||||
rejectExitCapture();
|
||||
String src = source.toString();
|
||||
// Always rename reserved words for the target GLSL version (e.g. 'sampler' at 460)
|
||||
src = GlslTransformUtils.renameReservedWords(src, RENDER_BACKEND.getMinGLSLVersion());
|
||||
if (ShaderManager.isEnabled()) {
|
||||
final int shaderType = RENDER_BACKEND.getShaderi(shader, GL20.GL_SHADER_TYPE);
|
||||
src = CompatShaderTransformer.transform(src, shaderType, shaderType == GL20.GL_FRAGMENT_SHADER);
|
||||
}
|
||||
RENDER_BACKEND.shaderSource(shader, src);
|
||||
}
|
||||
|
||||
public static void nglShaderSource(int shader, int count, long strings, long lengths) {
|
||||
rejectExitCapture();
|
||||
if (count <= 0) return;
|
||||
final CharSequence source;
|
||||
if (count == 1) {
|
||||
source = decodeShaderSourceString(strings, lengths, 0);
|
||||
} else {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < count; i++) sb.append(decodeShaderSourceString(strings, lengths, i));
|
||||
source = sb.toString();
|
||||
}
|
||||
glShaderSource(shader, source);
|
||||
}
|
||||
|
||||
private static String decodeShaderSourceString(long strings, long lengths, int i) {
|
||||
final long strAddr = MemoryUtilities.memGetAddress(strings + (long) i * Pointer.POINTER_SIZE);
|
||||
final int len = lengths == MemoryUtilities.NULL ? -1 : MemoryUtilities.memGetInt(lengths + (long) i * 4);
|
||||
return len < 0 ? MemoryUtilities.memUTF8(strAddr) : MemoryUtilities.memUTF8(strAddr, len);
|
||||
}
|
||||
|
||||
public static void glShaderSource(int shader, ByteBuffer source) {
|
||||
final byte[] bytes = new byte[source.remaining()];
|
||||
final int pos = source.position();
|
||||
source.get(bytes);
|
||||
source.position(pos);
|
||||
glShaderSource(shader, new String(bytes, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public static void glShaderSource(int shader, CharSequence[] sources) {
|
||||
int totalLen = 0;
|
||||
for (CharSequence s : sources) totalLen += s.length();
|
||||
final StringBuilder sb = new StringBuilder(totalLen);
|
||||
for (CharSequence s : sources) sb.append(s);
|
||||
glShaderSource(shader, sb.toString());
|
||||
}
|
||||
|
||||
public static void glSpecializeShader(int shader, CharSequence entryPoint, IntBuffer constantIndex, IntBuffer constantValue) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.specializeShader(shader, entryPoint, constantIndex, constantValue);
|
||||
}
|
||||
|
||||
public static int glGetUniformBlockIndex(int program, CharSequence name) { rejectExitCapture(); return RENDER_BACKEND.getUniformBlockIndex(program, name); }
|
||||
public static void glUniformBlockBinding(int program, int blockIndex, int binding) { rejectExitCapture(); RENDER_BACKEND.uniformBlockBinding(program, blockIndex, binding); }
|
||||
public static void glBindFragDataLocation(int program, int colorNumber, CharSequence name) { rejectExitCapture(); RENDER_BACKEND.bindFragDataLocation(program, colorNumber, name); }
|
||||
public static void glUniform3(int location, float[] values) { rejectExitCapture(); RENDER_BACKEND.uniform3fv(location, values); }
|
||||
public static void glUniform4(int location, float[] values) { rejectExitCapture(); RENDER_BACKEND.uniform4fv(location, values); }
|
||||
|
||||
public static void glLinkProgram(int program) {
|
||||
rejectExitCapture();
|
||||
if (ShaderManager.isEnabled()) {
|
||||
generateVertexShaderIfNeeded(program);
|
||||
}
|
||||
if (ProgramBinaryCache.isEnabled()) {
|
||||
ProgramBinaryCache.markRetrievable(program);
|
||||
}
|
||||
RENDER_BACKEND.linkProgram(program);
|
||||
if (ShaderManager.isEnabled() && RENDER_BACKEND.getProgrami(program, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) {
|
||||
LOGGER.warn("Program {} failed to link: {}", program, RENDER_BACKEND.getProgramInfoLog(program));
|
||||
}
|
||||
CompatUniformManager.onLinkProgram(program);
|
||||
}
|
||||
|
||||
public static void glProgramParameteri(int program, int pname, int value) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.programParameteri(program, pname, value);
|
||||
}
|
||||
|
||||
public static void glGetProgramBinary(int program, IntBuffer length, IntBuffer binaryFormat, ByteBuffer binary) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.getProgramBinary(program, length, binaryFormat, binary);
|
||||
}
|
||||
|
||||
public static void glProgramBinary(int program, int binaryFormat, ByteBuffer binary) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.programBinary(program, binaryFormat, binary);
|
||||
if (RENDER_BACKEND.getProgrami(program, GL20.GL_LINK_STATUS) == GL11.GL_TRUE) {
|
||||
CompatUniformManager.onLinkProgram(program);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a program has a fragment shader but no vertex shader, generate a passthrough vertex shader from the fragment's in declarations and attach it.
|
||||
*/
|
||||
private static void generateVertexShaderIfNeeded(int program) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final int shaderCount = RENDER_BACKEND.getProgrami(program, GL20.GL_ATTACHED_SHADERS);
|
||||
if (shaderCount == 0 || shaderCount > glCtx.shaderBuf.capacity()) return;
|
||||
|
||||
glCtx.shaderBuf.clear().limit(shaderCount);
|
||||
RENDER_BACKEND.getAttachedShaders(program, null, glCtx.shaderBuf);
|
||||
|
||||
int fragmentShader = 0;
|
||||
boolean hasVertex = false;
|
||||
for (int i = 0; i < shaderCount; i++) {
|
||||
final int shader = glCtx.shaderBuf.get(i);
|
||||
final int type = RENDER_BACKEND.getShaderi(shader, GL20.GL_SHADER_TYPE);
|
||||
if (type == GL20.GL_VERTEX_SHADER) {
|
||||
hasVertex = true;
|
||||
break;
|
||||
} else if (type == GL20.GL_FRAGMENT_SHADER) {
|
||||
fragmentShader = shader;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasVertex || fragmentShader == 0) return;
|
||||
|
||||
// Fragment-only program - generate a passthrough vertex shader
|
||||
final String fragSource = RENDER_BACKEND.getShaderSource(fragmentShader, 65536);
|
||||
String vertSource = CompatShaderTransformer.generatePassthroughVertexShader(fragSource);
|
||||
if (RenderSystem.isGLES()) {
|
||||
vertSource = CompatShaderTransformer.toGLES(vertSource, GL20.GL_VERTEX_SHADER, false);
|
||||
}
|
||||
|
||||
final int vertShader = RENDER_BACKEND.createShader(GL20.GL_VERTEX_SHADER);
|
||||
RENDER_BACKEND.shaderSource(vertShader, vertSource);
|
||||
RENDER_BACKEND.compileShader(vertShader);
|
||||
|
||||
if (RENDER_BACKEND.getShaderi(vertShader, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
|
||||
final String log = RENDER_BACKEND.getShaderInfoLog(vertShader, 8192);
|
||||
LOGGER.warn("CompatShaderTransformer: Generated passthrough vertex shader failed to compile:\n{}\nSource:\n{}", log, vertSource);
|
||||
RENDER_BACKEND.deleteShader(vertShader);
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.debug("CompatShaderTransformer: Generated passthrough vertex shader for fragment-only program {}", program);
|
||||
RENDER_BACKEND.attachShader(program, vertShader);
|
||||
RENDER_BACKEND.deleteShader(vertShader);
|
||||
}
|
||||
|
||||
@Getter
|
||||
static long programLifetimeGeneration;
|
||||
private static final IntOpenHashSet programsPendingDeletion = new IntOpenHashSet();
|
||||
|
||||
public static boolean isProgramPendingDeletion(int program) {
|
||||
return programsPendingDeletion.contains(program);
|
||||
}
|
||||
|
||||
public static void glDeleteProgram(int program) {
|
||||
rejectExitCapture();
|
||||
if (program == 0) return;
|
||||
CompatUniformManager.onDeleteProgram(program);
|
||||
|
||||
// GL defers deletion of a bound program until unbind; activeProgram stays set so the
|
||||
// cache matches GL_CURRENT_PROGRAM and the next glUseProgram is not skipped as redundant.
|
||||
if (GLSMHooks.PROGRAM_DELETE.hasListeners()) {
|
||||
GLSMHooks.programDeleteEvent.program = program;
|
||||
GLSMHooks.PROGRAM_DELETE.post(GLSMHooks.programDeleteEvent);
|
||||
}
|
||||
RENDER_BACKEND.deleteProgram(program);
|
||||
programsPendingDeletion.add(program);
|
||||
programsPendingDeletion.removeIf((int id) -> !RENDER_BACKEND.isProgram(id));
|
||||
programLifetimeGeneration++;
|
||||
}
|
||||
|
||||
public static int glCreateShader(int type) {
|
||||
requireContext("glCreateShader");
|
||||
return RENDER_BACKEND.createShader(type);
|
||||
}
|
||||
|
||||
public static void glCompileShader(int shader) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.compileShader(shader);
|
||||
}
|
||||
|
||||
public static int glCreateProgram() {
|
||||
requireContext("glCreateProgram");
|
||||
final int program = RENDER_BACKEND.createProgram();
|
||||
programsPendingDeletion.remove(program);
|
||||
programLifetimeGeneration++;
|
||||
return program;
|
||||
}
|
||||
|
||||
public static void glAttachShader(int program, int shader) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.attachShader(program, shader);
|
||||
}
|
||||
|
||||
public static void glDetachShader(int program, int shader) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.detachShader(program, shader);
|
||||
}
|
||||
|
||||
public static void glDeleteShader(int shader) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.deleteShader(shader);
|
||||
}
|
||||
|
||||
public static void glBindAttribLocation(int program, int index, CharSequence name) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.bindAttribLocation(program, index, name);
|
||||
}
|
||||
|
||||
public static void glValidateProgram(int program) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.validateProgram(program);
|
||||
}
|
||||
|
||||
public static int glGetShaderi(int shader, int pname) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getShaderi(shader, pname);
|
||||
}
|
||||
|
||||
public static String glGetShaderInfoLog(int shader, int maxLength) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getShaderInfoLog(shader, maxLength);
|
||||
}
|
||||
|
||||
public static String glGetShaderInfoLog(int shader) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getShaderInfoLog(shader);
|
||||
}
|
||||
|
||||
public static int glGetProgrami(int program, int pname) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getProgrami(program, pname);
|
||||
}
|
||||
|
||||
public static String glGetProgramInfoLog(int program, int maxLength) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getProgramInfoLog(program, maxLength);
|
||||
}
|
||||
|
||||
public static String glGetProgramInfoLog(int program) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getProgramInfoLog(program);
|
||||
}
|
||||
|
||||
public static boolean glIsProgram(int obj) {
|
||||
rejectExitCapture();
|
||||
final boolean valid = RENDER_BACKEND.isProgram(obj);
|
||||
if (!valid) programsPendingDeletion.remove(obj);
|
||||
return valid;
|
||||
}
|
||||
|
||||
public static boolean glIsShader(int obj) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.isShader(obj);
|
||||
}
|
||||
public static void glDispatchCompute(int x, int y, int z) { rejectExitCapture(); RENDER_BACKEND.dispatchCompute(x, y, z); }
|
||||
|
||||
public static int glGetUniformLocation(int program, CharSequence name) {
|
||||
rejectExitCapture();
|
||||
int loc = RENDER_BACKEND.getUniformLocation(program, name);
|
||||
if (loc == -1 && TEXTURE.contentEquals(name)) {
|
||||
loc = RENDER_BACKEND.getUniformLocation(program, TEXTURE_RENAMED);
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
public static int glGetUniformLocation(int program, ByteBuffer name) {
|
||||
rejectExitCapture();
|
||||
int loc = RENDER_BACKEND.getUniformLocation(program, name);
|
||||
if (loc == -1 && isTextureBuffer(name)) {
|
||||
loc = RENDER_BACKEND.getUniformLocation(program, TEXTURE_RENAMED);
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
public static int glGetAttribLocation(int program, CharSequence name) {
|
||||
rejectExitCapture();
|
||||
int loc = RENDER_BACKEND.getAttribLocation(program, name);
|
||||
if (loc == -1 && TEXTURE.contentEquals(name)) {
|
||||
loc = RENDER_BACKEND.getAttribLocation(program, TEXTURE_RENAMED);
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
public static int glGetAttribLocation(int program, ByteBuffer name) {
|
||||
rejectExitCapture();
|
||||
int loc = RENDER_BACKEND.getAttribLocation(program, name);
|
||||
if (loc == -1 && isTextureBuffer(name)) {
|
||||
loc = RENDER_BACKEND.getAttribLocation(program, TEXTURE_RENAMED);
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
private static final ByteBuffer TEXTURE_BYTES = ByteBuffer.wrap(TEXTURE.getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
private static boolean isTextureBuffer(ByteBuffer buf) {
|
||||
final int len = buf.remaining();
|
||||
if (len != 7 && len != 8) return false;
|
||||
// I believe the driver accepts null terminated or not
|
||||
if (len == 8 && buf.get(buf.position() + 7) != 0) return false;
|
||||
return buf.slice(buf.position(), 7).equals(TEXTURE_BYTES);
|
||||
}
|
||||
|
||||
public static void glDeleteObjectARB(int obj) {
|
||||
rejectExitCapture();
|
||||
if (RENDER_BACKEND.isShader(obj)) {
|
||||
RENDER_BACKEND.deleteShader(obj);
|
||||
} else {
|
||||
glDeleteProgram(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public static int glGetHandleARB(int pname) {
|
||||
rejectExitCapture();
|
||||
return pname == ARBShaderObjects.GL_PROGRAM_OBJECT_ARB ? GLSMQueries.glGetInteger(GL20.GL_CURRENT_PROGRAM) : RENDER_BACKEND.getInteger(pname);
|
||||
}
|
||||
|
||||
public static void glGetObjectParameterARB(int obj, int pname, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
final var backend = RENDER_BACKEND;
|
||||
if (backend.isShader(obj)) {
|
||||
params.put(params.position(), backend.getShaderi(obj, pname));
|
||||
} else {
|
||||
backend.getProgramiv(obj, pname, params);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glGetObjectParameterARB(int obj, int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final var backend = RENDER_BACKEND;
|
||||
params.put(params.position(), (float) (backend.isShader(obj) ? backend.getShaderi(obj, pname) : backend.getProgrami(obj, pname)));
|
||||
}
|
||||
|
||||
public static int glGetObjectParameteriARB(int obj, int pname) {
|
||||
rejectExitCapture();
|
||||
final var backend = RENDER_BACKEND;
|
||||
return backend.isShader(obj) ? backend.getShaderi(obj, pname) : backend.getProgrami(obj, pname);
|
||||
}
|
||||
|
||||
public static String glGetInfoLogARB(int obj, int maxLength) {
|
||||
rejectExitCapture();
|
||||
final var backend = RENDER_BACKEND;
|
||||
return backend.isShader(obj) ? backend.getShaderInfoLog(obj, maxLength) : backend.getProgramInfoLog(obj, maxLength);
|
||||
}
|
||||
|
||||
public static void glGetInfoLogARB(int obj, IntBuffer length, ByteBuffer infoLog) {
|
||||
rejectExitCapture();
|
||||
final var backend = RENDER_BACKEND;
|
||||
if (backend.isShader(obj)) {
|
||||
backend.getShaderInfoLog(obj, length, infoLog);
|
||||
} else {
|
||||
backend.getProgramInfoLog(obj, length, infoLog);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glUniform1f(int location, float v0) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform1f(location, v0);
|
||||
}
|
||||
|
||||
public static void glUniform2f(int location, float v0, float v1) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform2f(location, v0, v1);
|
||||
}
|
||||
|
||||
public static void glUniform3f(int location, float v0, float v1, float v2) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform3f(location, v0, v1, v2);
|
||||
}
|
||||
|
||||
public static void glUniform4f(int location, float v0, float v1, float v2, float v3) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform4f(location, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
public static void glUniform1i(int location, int v0) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform1i(location, v0);
|
||||
}
|
||||
|
||||
public static void glUniform2i(int location, int v0, int v1) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform2i(location, v0, v1);
|
||||
}
|
||||
|
||||
public static void glUniform3i(int location, int v0, int v1, int v2) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform3i(location, v0, v1, v2);
|
||||
}
|
||||
|
||||
public static void glUniform4i(int location, int v0, int v1, int v2, int v3) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform4i(location, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
public static void glUniform1(int location, FloatBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform1fv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform1(int location, IntBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform1iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform2(int location, FloatBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform2(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform2(int location, IntBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform2iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform3(int location, FloatBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform3(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform3(int location, IntBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform3iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform4(int location, FloatBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform4(location, values);
|
||||
}
|
||||
|
||||
public static void glUniform4(int location, IntBuffer values) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniform4iv(location, values);
|
||||
}
|
||||
|
||||
public static void glUniformMatrix2(int location, boolean transpose, FloatBuffer matrices) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniformMatrix2(location, transpose, matrices);
|
||||
}
|
||||
|
||||
public static void glUniformMatrix3(int location, boolean transpose, FloatBuffer matrices) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniformMatrix3(location, transpose, matrices);
|
||||
}
|
||||
|
||||
public static void glUniformMatrix4(int location, boolean transpose, FloatBuffer matrices) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.uniformMatrix4(location, transpose, matrices);
|
||||
}
|
||||
|
||||
public static void glGetActiveUniform(int program, int index, IntBuffer length, IntBuffer size, IntBuffer type, ByteBuffer name) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.getActiveUniform(program, index, length, size, type, name);
|
||||
}
|
||||
|
||||
public static void glGetActiveAttrib(int program, int index, IntBuffer length, IntBuffer size, IntBuffer type, ByteBuffer name) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.getActiveAttrib(program, index, length, size, type, name);
|
||||
}
|
||||
|
||||
public static String glGetActiveAttrib(int program, int index, int maxLength, IntBuffer sizeType) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getActiveAttrib(program, index, maxLength, sizeType);
|
||||
}
|
||||
|
||||
public static void glGetAttachedShaders(int program, IntBuffer count, IntBuffer shaders) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.getAttachedShaders(program, count, shaders);
|
||||
}
|
||||
|
||||
public static String glGetShaderSource(int shader, int maxLength) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.getShaderSource(shader, maxLength);
|
||||
}
|
||||
|
||||
public static void glGetShaderSource(int shader, IntBuffer length, ByteBuffer source) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.getShaderSource(shader, length, source);
|
||||
}
|
||||
|
||||
public static void glGetUniform(int program, int location, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.getUniformfv(program, location, params);
|
||||
}
|
||||
|
||||
public static void glGetUniform(int program, int location, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
RENDER_BACKEND.getUniformiv(program, location, params);
|
||||
}
|
||||
|
||||
public static int getProgramGeneration() {
|
||||
return ctx().programGeneration;
|
||||
}
|
||||
|
||||
public static IntegerStateStack getProgramStack() {
|
||||
return ctx().programStack;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getVertexProgramTwoSideState() {
|
||||
return ctx().vertexProgramTwoSideState;
|
||||
}
|
||||
|
||||
public static int getActiveProgram() {
|
||||
return ctx().activeProgram;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,594 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.states.PolygonState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ImageUnitBinding;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
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.GL21;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
import org.lwjgl.opengl.GL42;
|
||||
import org.lwjgl.opengl.GL43;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.HAS_MULTIPLE_SET;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_ATTRIB_STACK_DEPTH;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_CLIP_PLANES;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_LEGACY_TEXTURE_UNITS;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_MODELVIEW_STACK_DEPTH;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_PROJECTION_STACK_DEPTH;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_TEXTURE_COORDS;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_TEXTURE_STACK_DEPTH;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.initConfig;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.requireContext;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMQueries {
|
||||
|
||||
private GLSMQueries() {}
|
||||
|
||||
public static boolean glGetBoolean(int pname) {
|
||||
rejectExitCapture();
|
||||
return glGetBoolean(ctx(), pname);
|
||||
}
|
||||
|
||||
static boolean glGetBoolean(GLContextState glCtx, int pname) {
|
||||
if (!isCachingEnabled()) {
|
||||
return RENDER_BACKEND.getBoolean(pname);
|
||||
}
|
||||
// Handle clip planes dynamically (supports up to MAX_CLIP_PLANES)
|
||||
if (pname >= GL11.GL_CLIP_PLANE0 && pname < GL11.GL_CLIP_PLANE0 + MAX_CLIP_PLANES) {
|
||||
return glCtx.clipPlaneStates[pname - GL11.GL_CLIP_PLANE0].isEnabled();
|
||||
}
|
||||
|
||||
return switch (pname) {
|
||||
case GL11.GL_ALPHA_TEST -> glCtx.alphaTest.isEnabled();
|
||||
case GL11.GL_AUTO_NORMAL -> glCtx.autoNormalState.isEnabled();
|
||||
case GL11.GL_BLEND -> glCtx.blendMode.isEnabled();
|
||||
case GL11.GL_COLOR_MATERIAL -> glCtx.colorMaterial.isEnabled();
|
||||
case GL11.GL_COLOR_LOGIC_OP -> glCtx.colorLogicOpState.isEnabled();
|
||||
case GL14.GL_COLOR_SUM -> glCtx.colorSumState.isEnabled();
|
||||
case GL11.GL_CULL_FACE -> glCtx.cullState.isEnabled();
|
||||
case GL11.GL_DEPTH_TEST -> glCtx.depthTest.isEnabled();
|
||||
case GL11.GL_DEPTH_WRITEMASK -> glCtx.depthState.isEnabled();
|
||||
case GL11.GL_DITHER -> glCtx.ditherState.isEnabled();
|
||||
case GL11.GL_FOG -> glCtx.fogMode.isEnabled();
|
||||
case GL11.GL_INDEX_LOGIC_OP -> glCtx.indexLogicOpState.isEnabled();
|
||||
case GL11.GL_LIGHTING -> glCtx.lightingState.isEnabled();
|
||||
case GL11.GL_LIGHT0 -> glCtx.lightStates[0].isEnabled();
|
||||
case GL11.GL_LIGHT1 -> glCtx.lightStates[1].isEnabled();
|
||||
case GL11.GL_LIGHT2 -> glCtx.lightStates[2].isEnabled();
|
||||
case GL11.GL_LIGHT3 -> glCtx.lightStates[3].isEnabled();
|
||||
case GL11.GL_LIGHT4 -> glCtx.lightStates[4].isEnabled();
|
||||
case GL11.GL_LIGHT5 -> glCtx.lightStates[5].isEnabled();
|
||||
case GL11.GL_LIGHT6 -> glCtx.lightStates[6].isEnabled();
|
||||
case GL11.GL_LIGHT7 -> glCtx.lightStates[7].isEnabled();
|
||||
case GL11.GL_LINE_SMOOTH -> glCtx.lineSmoothState.isEnabled();
|
||||
case GL11.GL_LINE_STIPPLE -> glCtx.lineStippleState.isEnabled();
|
||||
case GL11.GL_MAP1_COLOR_4 -> glCtx.map1Color4State.isEnabled();
|
||||
case GL11.GL_MAP1_INDEX -> glCtx.map1IndexState.isEnabled();
|
||||
case GL11.GL_MAP1_NORMAL -> glCtx.map1NormalState.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_1 -> glCtx.map1TextureCoord1State.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_2 -> glCtx.map1TextureCoord2State.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_3 -> glCtx.map1TextureCoord3State.isEnabled();
|
||||
case GL11.GL_MAP1_TEXTURE_COORD_4 -> glCtx.map1TextureCoord4State.isEnabled();
|
||||
case GL11.GL_MAP1_VERTEX_3 -> glCtx.map1Vertex3State.isEnabled();
|
||||
case GL11.GL_MAP1_VERTEX_4 -> glCtx.map1Vertex4State.isEnabled();
|
||||
case GL11.GL_MAP2_COLOR_4 -> glCtx.map2Color4State.isEnabled();
|
||||
case GL11.GL_MAP2_INDEX -> glCtx.map2IndexState.isEnabled();
|
||||
case GL11.GL_MAP2_NORMAL -> glCtx.map2NormalState.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_1 -> glCtx.map2TextureCoord1State.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_2 -> glCtx.map2TextureCoord2State.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_3 -> glCtx.map2TextureCoord3State.isEnabled();
|
||||
case GL11.GL_MAP2_TEXTURE_COORD_4 -> glCtx.map2TextureCoord4State.isEnabled();
|
||||
case GL11.GL_MAP2_VERTEX_3 -> glCtx.map2Vertex3State.isEnabled();
|
||||
case GL11.GL_MAP2_VERTEX_4 -> glCtx.map2Vertex4State.isEnabled();
|
||||
case GL13.GL_MULTISAMPLE -> glCtx.multisampleState.isEnabled();
|
||||
case GL11.GL_NORMALIZE -> glCtx.normalizeState.isEnabled();
|
||||
case GL11.GL_POINT_SMOOTH -> glCtx.pointSmoothState.isEnabled();
|
||||
case GL20.GL_POINT_SPRITE -> glCtx.pointSpriteState.isEnabled();
|
||||
case GL20.GL_VERTEX_PROGRAM_TWO_SIDE -> glCtx.vertexProgramTwoSideState.isEnabled();
|
||||
case GL11.GL_POLYGON_OFFSET_POINT -> glCtx.polygonOffsetPointState.isEnabled();
|
||||
case GL11.GL_POLYGON_OFFSET_LINE -> glCtx.polygonOffsetLineState.isEnabled();
|
||||
case GL11.GL_POLYGON_OFFSET_FILL -> glCtx.polygonOffsetFillState.isEnabled();
|
||||
case GL11.GL_POLYGON_SMOOTH -> glCtx.polygonSmoothState.isEnabled();
|
||||
case GL11.GL_POLYGON_STIPPLE -> glCtx.polygonStippleState.isEnabled();
|
||||
case GL12.GL_RESCALE_NORMAL -> glCtx.rescaleNormalState.isEnabled();
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_COVERAGE -> glCtx.sampleAlphaToCoverageState.isEnabled();
|
||||
case GL13.GL_SAMPLE_ALPHA_TO_ONE -> glCtx.sampleAlphaToOneState.isEnabled();
|
||||
case GL13.GL_SAMPLE_COVERAGE -> glCtx.sampleCoverageState.isEnabled();
|
||||
case GL30.GL_RASTERIZER_DISCARD -> glCtx.rasterizerDiscard.isEnabled();
|
||||
case GL11.GL_SCISSOR_TEST -> glCtx.scissorTest.isEnabled();
|
||||
case GL11.GL_STENCIL_TEST -> glCtx.stencilTest.isEnabled();
|
||||
case GL11.GL_TEXTURE_1D -> glCtx.textures.getTexture1DStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_2D -> glCtx.textures.getTextureUnitStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL12.GL_TEXTURE_3D -> glCtx.textures.getTexture3DStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL13.GL_TEXTURE_CUBE_MAP -> glCtx.textures.getTextureCubeMapStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_S -> glCtx.textures.getTexGenSStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_T -> glCtx.textures.getTexGenTStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_R -> glCtx.textures.getTexGenRStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_TEXTURE_GEN_Q -> glCtx.textures.getTexGenQStates(glCtx.activeTextureUnit.getValue()).isEnabled();
|
||||
case GL11.GL_LIGHT_MODEL_LOCAL_VIEWER -> glCtx.lightModel.localViewer != 0.0f;
|
||||
case GL11.GL_LIGHT_MODEL_TWO_SIDE -> glCtx.lightModel.twoSide != 0.0f;
|
||||
case GL11.GL_EDGE_FLAG -> glCtx.edgeFlagState.isEnabled();
|
||||
default -> {
|
||||
final int conv = GLSMVertexInput.clientStateToConventional(glCtx, pname);
|
||||
if (conv >= 0) yield glCtx.vaos.isConventionalEnabled(conv);
|
||||
final int desc = LegacyQueries.desc(pname);
|
||||
yield desc != 0 ? LegacyQueries.getBoolean(glCtx, pname, desc) : RENDER_BACKEND.getBoolean(pname);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void glGetBoolean(int pname, ByteBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) {
|
||||
RENDER_BACKEND.getBoolean(pname, params);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL11.GL_COLOR_WRITEMASK -> {
|
||||
final int pos = params.position();
|
||||
params.put(pos, (byte) (glCtx.colorMask.red ? GL11.GL_TRUE : GL11.GL_FALSE));
|
||||
params.put(pos + 1, (byte) (glCtx.colorMask.green ? GL11.GL_TRUE : GL11.GL_FALSE));
|
||||
params.put(pos + 2, (byte) (glCtx.colorMask.blue ? GL11.GL_TRUE : GL11.GL_FALSE));
|
||||
params.put(pos + 3, (byte) (glCtx.colorMask.alpha ? GL11.GL_TRUE : GL11.GL_FALSE));
|
||||
}
|
||||
default -> {
|
||||
if (!HAS_MULTIPLE_SET.contains(pname)) {
|
||||
params.put(params.position(), (byte) (glGetBoolean(glCtx, pname) ? GL11.GL_TRUE : GL11.GL_FALSE));
|
||||
} else if (!LegacyQueries.getBooleanv(glCtx, pname, params)) {
|
||||
RENDER_BACKEND.getBoolean(pname, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int glGetInteger(int pname) {
|
||||
rejectExitCapture();
|
||||
return glGetInteger(ctx(), pname);
|
||||
}
|
||||
|
||||
static int glGetInteger(GLContextState glCtx, int pname) {
|
||||
if (!isCachingEnabled()) {
|
||||
return RENDER_BACKEND.getInteger(pname);
|
||||
}
|
||||
|
||||
return switch (pname) {
|
||||
case GL11.GL_ALPHA_TEST_FUNC -> glCtx.alphaState.getFunction();
|
||||
case GL11.GL_DEPTH_FUNC -> glCtx.depthState.getFunc();
|
||||
case GL11.GL_LIST_BASE -> glCtx.listBase;
|
||||
case GL11.GL_LIST_MODE -> DisplayListManager.getListMode();
|
||||
case GL11.GL_MATRIX_MODE -> glCtx.matrixMode.getMode();
|
||||
case GL11.GL_SHADE_MODEL -> glCtx.shadeModelState.getValue();
|
||||
// GL_TEXTURE_2D makes no sense here, but some mod still queries it...
|
||||
case GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_BINDING_2D -> GLSMTextures.getBoundTextureForServerState();
|
||||
case GL13.GL_ACTIVE_TEXTURE -> GL13.GL_TEXTURE0 + GLSMTextures.getActiveTextureUnitForServerState();
|
||||
case GL13.GL_CLIENT_ACTIVE_TEXTURE -> GL13.GL_TEXTURE0 + glCtx.clientActiveTextureUnit;
|
||||
case GL11.GL_COLOR_MATERIAL_FACE -> glCtx.colorMaterialFace.getValue();
|
||||
case GL11.GL_COLOR_MATERIAL_PARAMETER -> glCtx.colorMaterialParameter.getValue();
|
||||
case GL11.GL_MODELVIEW_STACK_DEPTH -> GLSMMatrices.getMatrixStackDepth(glCtx.modelViewMatrix);
|
||||
case GL11.GL_PROJECTION_STACK_DEPTH -> GLSMMatrices.getMatrixStackDepth(glCtx.projectionMatrix);
|
||||
case GL11.GL_DEPTH_WRITEMASK -> glCtx.depthState.isEnabled() ? GL11.GL_TRUE : GL11.GL_FALSE;
|
||||
case GL11.GL_CULL_FACE_MODE -> glCtx.polygonState.getCullFaceMode();
|
||||
case GL11.GL_FRONT_FACE -> glCtx.polygonState.getFrontFace();
|
||||
case GL11.GL_POLYGON_MODE -> glCtx.polygonState.getFrontMode();
|
||||
case GL11.GL_UNPACK_ALIGNMENT -> glCtx.pixelUnpackState.alignment();
|
||||
case GL11.GL_UNPACK_ROW_LENGTH -> glCtx.pixelUnpackState.rowLength();
|
||||
case GL11.GL_UNPACK_SKIP_ROWS -> glCtx.pixelUnpackState.skipRows();
|
||||
case GL11.GL_UNPACK_SKIP_PIXELS -> glCtx.pixelUnpackState.skipPixels();
|
||||
|
||||
case GL12.GL_LIGHT_MODEL_COLOR_CONTROL -> glCtx.lightModel.colorControl;
|
||||
|
||||
case GL14.GL_BLEND_DST_ALPHA -> glCtx.blendState.getDstAlpha();
|
||||
case GL11.GL_BLEND_DST, GL14.GL_BLEND_DST_RGB -> glCtx.blendState.getDstRgb();
|
||||
case GL14.GL_BLEND_SRC_ALPHA -> glCtx.blendState.getSrcAlpha();
|
||||
case GL11.GL_BLEND_SRC, GL14.GL_BLEND_SRC_RGB -> glCtx.blendState.getSrcRgb();
|
||||
case GL14.GL_BLEND_EQUATION -> glCtx.blendState.getEquationRgb();
|
||||
case GL20.GL_BLEND_EQUATION_ALPHA -> glCtx.blendState.getEquationAlpha();
|
||||
|
||||
case GL11.GL_LOGIC_OP_MODE -> glCtx.logicOpMode.getValue();
|
||||
case GL11.GL_DRAW_BUFFER -> glCtx.drawBuffer.getValue();
|
||||
|
||||
case GL11.GL_STENCIL_FUNC -> glCtx.stencilState.getFuncFront();
|
||||
case GL11.GL_STENCIL_REF -> glCtx.stencilState.getRefFront();
|
||||
case GL11.GL_STENCIL_VALUE_MASK -> glCtx.stencilState.getValueMaskFront();
|
||||
case GL11.GL_STENCIL_FAIL -> glCtx.stencilState.getFailOpFront();
|
||||
case GL11.GL_STENCIL_PASS_DEPTH_FAIL -> glCtx.stencilState.getZFailOpFront();
|
||||
case GL11.GL_STENCIL_PASS_DEPTH_PASS -> glCtx.stencilState.getZPassOpFront();
|
||||
case GL11.GL_STENCIL_WRITEMASK -> glCtx.stencilState.getWriteMaskFront();
|
||||
case GL11.GL_STENCIL_CLEAR_VALUE -> glCtx.stencilState.getClearValue();
|
||||
|
||||
case GL15.GL_ARRAY_BUFFER_BINDING -> glCtx.boundVBO;
|
||||
case GL15.GL_ELEMENT_ARRAY_BUFFER_BINDING -> glCtx.vaos.boundEBO;
|
||||
case GL21.GL_PIXEL_UNPACK_BUFFER_BINDING -> glCtx.boundPixelUnpackBuffer;
|
||||
case GL21.GL_PIXEL_PACK_BUFFER_BINDING -> glCtx.boundPixelPackBuffer;
|
||||
|
||||
case GL20.GL_CURRENT_PROGRAM -> glCtx.activeProgram;
|
||||
|
||||
case GL30.GL_VERTEX_ARRAY_BINDING -> glCtx.boundVAO;
|
||||
|
||||
case GL30.GL_DRAW_FRAMEBUFFER_BINDING -> glCtx.drawFramebuffer;
|
||||
case GL30.GL_READ_FRAMEBUFFER_BINDING -> glCtx.readFramebuffer;
|
||||
|
||||
case GL33.GL_SAMPLER_BINDING -> glCtx.samplerUnits.get(glCtx.activeTextureUnit.getValue());
|
||||
|
||||
default -> switch (pname) {
|
||||
case GL11.GL_FOG_MODE -> glCtx.fogState.getFogMode();
|
||||
case GL11.GL_LINE_STIPPLE_PATTERN -> glCtx.lineState.getStipplePattern() & 0xFFFF;
|
||||
case GL11.GL_LINE_STIPPLE_REPEAT -> glCtx.lineState.getStippleFactor();
|
||||
case GL11.GL_LIST_INDEX -> DisplayListManager.isRecording() ? Math.max(DisplayListManager.getRecordingListId(), 0) : 0;
|
||||
case GL11.GL_ATTRIB_STACK_DEPTH -> glCtx.attribDepth;
|
||||
case GL11.GL_CLIENT_ATTRIB_STACK_DEPTH -> glCtx.clientAttribStackPointer;
|
||||
case GL11.GL_TEXTURE_STACK_DEPTH -> GLSMMatrices.getMatrixStackDepth(glCtx.textures.getTextureUnitMatrix(glCtx.activeTextureUnit.getValue()));
|
||||
case GL11.GL_MAX_ATTRIB_STACK_DEPTH -> MAX_ATTRIB_STACK_DEPTH;
|
||||
case GL11.GL_MAX_CLIENT_ATTRIB_STACK_DEPTH -> GLSMAttribStack.CLIENT_ATTRIB_STACK_DEPTH;
|
||||
case GL11.GL_MAX_MODELVIEW_STACK_DEPTH -> MAX_MODELVIEW_STACK_DEPTH;
|
||||
case GL11.GL_MAX_PROJECTION_STACK_DEPTH -> MAX_PROJECTION_STACK_DEPTH;
|
||||
case GL11.GL_MAX_TEXTURE_STACK_DEPTH -> MAX_TEXTURE_STACK_DEPTH;
|
||||
case GL13.GL_MAX_TEXTURE_UNITS -> MAX_LEGACY_TEXTURE_UNITS;
|
||||
case GL11.GL_MAX_LIGHTS -> glCtx.lightStates.length;
|
||||
case GL11.GL_STENCIL_BITS -> GLSMFramebuffer.drawFramebufferBits(glCtx, true);
|
||||
case GL11.GL_DEPTH_BITS -> GLSMFramebuffer.drawFramebufferBits(glCtx, false);
|
||||
case GL20.GL_MAX_TEXTURE_COORDS -> MAX_TEXTURE_COORDS;
|
||||
case GL20.GL_POINT_SPRITE_COORD_ORIGIN -> glCtx.pointState.getSpriteCoordOrigin();
|
||||
case GL11.GL_RENDER_MODE -> FeedbackManager.getRenderMode();
|
||||
default -> {
|
||||
final int shift = GLSMRasterizer.hintShift(pname);
|
||||
if (shift >= 0) yield GLSMRasterizer.hintMode(glCtx.hintState.getValue(), shift);
|
||||
final int key = GLSMVertexInput.clientArrayField(glCtx, pname);
|
||||
if (key >= 0 && (key & ~0xFF) != GLSMVertexInput.FIELD_POINTER) yield GLSMVertexInput.clientArrayParam(glCtx, key);
|
||||
final int desc = LegacyQueries.desc(pname);
|
||||
yield desc != 0 ? LegacyQueries.getInteger(glCtx, pname, desc) : RENDER_BACKEND.getInteger(pname);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
public static void glGetInteger(int pname, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
if (!isCachingEnabled()) {
|
||||
RENDER_BACKEND.getInteger(pname, params);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL11.GL_VIEWPORT -> ctx().viewportState.get(params);
|
||||
case GL11.GL_SCISSOR_BOX -> ctx().scissorState.get(params);
|
||||
case GL11.GL_POLYGON_MODE -> {
|
||||
final PolygonState polygon = ctx().polygonState;
|
||||
final int pos = params.position();
|
||||
params.put(pos, polygon.getFrontMode());
|
||||
params.put(pos + 1, polygon.getBackMode());
|
||||
}
|
||||
default -> {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!HAS_MULTIPLE_SET.contains(pname)) {
|
||||
params.put(params.position(), glGetInteger(glCtx, pname));
|
||||
} else if (!LegacyQueries.getIntegerv(glCtx, pname, params)) {
|
||||
RENDER_BACKEND.getInteger(pname, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glGetFloat(int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) {
|
||||
RENDER_BACKEND.getFloat(pname, params);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL11.GL_MODELVIEW_MATRIX -> glCtx.modelViewMatrix.get(params.position(), params);
|
||||
case GL11.GL_PROJECTION_MATRIX -> glCtx.projectionMatrix.get(params.position(), params);
|
||||
case GL11.GL_TEXTURE_MATRIX -> glCtx.textures.getTextureUnitMatrix(GLSMTextures.getActiveTextureUnit()).get(params.position(), params);
|
||||
case GL11.GL_COLOR_CLEAR_VALUE -> glCtx.clearColor.get(params);
|
||||
case GL11.GL_CURRENT_COLOR -> glCtx.color.get(params);
|
||||
case GL14.GL_CURRENT_SECONDARY_COLOR -> glCtx.secondaryColor.get(params);
|
||||
case GL11.GL_DEPTH_RANGE -> {
|
||||
final int pos = params.position();
|
||||
params.put(pos, (float) glCtx.viewportState.depthRangeNear);
|
||||
params.put(pos + 1, (float) glCtx.viewportState.depthRangeFar);
|
||||
}
|
||||
case GL14.GL_BLEND_COLOR -> {
|
||||
final int pos = params.position();
|
||||
params.put(pos, glCtx.blendState.getBlendColorR());
|
||||
params.put(pos + 1, glCtx.blendState.getBlendColorG());
|
||||
params.put(pos + 2, glCtx.blendState.getBlendColorB());
|
||||
params.put(pos + 3, glCtx.blendState.getBlendColorA());
|
||||
}
|
||||
case GL11.GL_CURRENT_NORMAL -> {
|
||||
final Vector3f normal = glCtx.ffp.currentNormal;
|
||||
final int pos = params.position();
|
||||
params.put(pos, normal.x);
|
||||
params.put(pos + 1, normal.y);
|
||||
params.put(pos + 2, normal.z);
|
||||
}
|
||||
case GL11.GL_CURRENT_TEXTURE_COORDS -> {
|
||||
final int unit = glCtx.activeTextureUnit.getValue();
|
||||
final int pos = params.position();
|
||||
if (unit == 1) {
|
||||
params.put(pos, glCtx.lastBrightnessX);
|
||||
params.put(pos + 1, glCtx.lastBrightnessY);
|
||||
params.put(pos + 2, 0.0f);
|
||||
params.put(pos + 3, 1.0f);
|
||||
} else if (unit >= 0 && unit < glCtx.ffp.currentTexCoords.length) {
|
||||
final Vector4f tc = glCtx.ffp.currentTexCoords[unit];
|
||||
params.put(pos, tc.x);
|
||||
params.put(pos + 1, tc.y);
|
||||
params.put(pos + 2, tc.z);
|
||||
params.put(pos + 3, tc.w);
|
||||
} else {
|
||||
params.put(pos, 0.0f);
|
||||
params.put(pos + 1, 0.0f);
|
||||
params.put(pos + 2, 0.0f);
|
||||
params.put(pos + 3, 1.0f);
|
||||
}
|
||||
}
|
||||
case GL11.GL_FOG_COLOR -> {
|
||||
final FloatBuffer fogBuf = glCtx.fogState.getFogColorBuffer();
|
||||
final int pos = params.position();
|
||||
params.put(pos, fogBuf.get(0));
|
||||
params.put(pos + 1, fogBuf.get(1));
|
||||
params.put(pos + 2, fogBuf.get(2));
|
||||
params.put(pos + 3, fogBuf.get(3));
|
||||
}
|
||||
case GL11.GL_LIGHT_MODEL_AMBIENT -> glCtx.lightModel.ambient.get(params.position(), params);
|
||||
case GL14.GL_POINT_DISTANCE_ATTENUATION -> {
|
||||
final int pos = params.position();
|
||||
params.put(pos, glCtx.pointState.getAttenuationConstant());
|
||||
params.put(pos + 1, glCtx.pointState.getAttenuationLinear());
|
||||
params.put(pos + 2, glCtx.pointState.getAttenuationQuadratic());
|
||||
}
|
||||
default -> {
|
||||
if (!HAS_MULTIPLE_SET.contains(pname)) {
|
||||
params.put(params.position(), glGetFloat(glCtx, pname));
|
||||
} else {
|
||||
RENDER_BACKEND.getFloat(pname, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static float glGetFloat(int pname) {
|
||||
rejectExitCapture();
|
||||
return glGetFloat(ctx(), pname);
|
||||
}
|
||||
|
||||
static float glGetFloat(GLContextState glCtx, int pname) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_ALPHA_TEST_REF -> glCtx.alphaState.getReference();
|
||||
case GL11.GL_FOG_DENSITY -> glCtx.fogState.getDensity();
|
||||
case GL11.GL_FOG_START -> glCtx.fogState.getStart();
|
||||
case GL11.GL_FOG_END -> glCtx.fogState.getEnd();
|
||||
case GL11.GL_DEPTH_CLEAR_VALUE -> (float) glCtx.depthState.getClearValue();
|
||||
case GL11.GL_LINE_WIDTH -> glCtx.lineState.getWidth();
|
||||
case GL11.GL_POINT_SIZE -> glCtx.pointState.getSize();
|
||||
case GL14.GL_POINT_SIZE_MIN -> glCtx.pointState.getMinSize();
|
||||
case GL14.GL_POINT_SIZE_MAX -> Float.isNaN(glCtx.pointState.getMaxSize()) ? GLSMRasterizer.maxPointSize : glCtx.pointState.getMaxSize();
|
||||
case GL14.GL_POINT_FADE_THRESHOLD_SIZE -> glCtx.pointState.getFadeThreshold();
|
||||
default -> {
|
||||
final int desc = isCachingEnabled() ? LegacyQueries.desc(pname) : 0;
|
||||
yield desc != 0 ? LegacyQueries.getFloat(glCtx, pname, desc) : RENDER_BACKEND.getFloat(pname);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void glGetFloat(int pname, float[] params) {
|
||||
final FloatBuffer scratch = ctx().queryScratch;
|
||||
final FloatBuffer buf;
|
||||
if (params.length <= scratch.capacity()) {
|
||||
buf = scratch;
|
||||
buf.clear();
|
||||
buf.limit(params.length);
|
||||
} else {
|
||||
buf = BufferUtils.createFloatBuffer(params.length);
|
||||
}
|
||||
glGetFloat(pname, buf);
|
||||
buf.position(0);
|
||||
buf.get(params);
|
||||
}
|
||||
|
||||
public static double glGetDouble(int pname) {
|
||||
rejectExitCapture();
|
||||
return switch (pname) {
|
||||
case GL11.GL_DEPTH_CLEAR_VALUE -> ctx().depthState.getClearValue();
|
||||
default -> glGetFloat(pname);
|
||||
};
|
||||
}
|
||||
|
||||
public static void glGetDouble(int pname, DoubleBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) {
|
||||
RENDER_BACKEND.getDouble(pname, params);
|
||||
return;
|
||||
}
|
||||
|
||||
final int pos = params.position();
|
||||
switch (pname) {
|
||||
case GL11.GL_DEPTH_CLEAR_VALUE -> params.put(pos, glCtx.depthState.getClearValue());
|
||||
case GL11.GL_DEPTH_RANGE -> {
|
||||
params.put(pos, glCtx.viewportState.depthRangeNear);
|
||||
params.put(pos + 1, glCtx.viewportState.depthRangeFar);
|
||||
}
|
||||
case GL11.GL_MODELVIEW_MATRIX, GL11.GL_PROJECTION_MATRIX, GL11.GL_TEXTURE_MATRIX -> widenFromFloat(pname, params, 16);
|
||||
case GL11.GL_COLOR_CLEAR_VALUE, GL11.GL_CURRENT_COLOR, GL11.GL_CURRENT_TEXTURE_COORDS, GL11.GL_FOG_COLOR,
|
||||
GL11.GL_LIGHT_MODEL_AMBIENT, GL14.GL_BLEND_COLOR, GL14.GL_CURRENT_SECONDARY_COLOR -> widenFromFloat(pname, params, 4);
|
||||
case GL11.GL_CURRENT_NORMAL, GL14.GL_POINT_DISTANCE_ATTENUATION -> widenFromFloat(pname, params, 3);
|
||||
default -> {
|
||||
if (!HAS_MULTIPLE_SET.contains(pname)) {
|
||||
params.put(pos, glGetDouble(pname));
|
||||
} else {
|
||||
RENDER_BACKEND.getDouble(pname, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glGetDouble(int pname, double[] params) {
|
||||
final DoubleBuffer scratch = ctx().queryScratchDouble;
|
||||
final DoubleBuffer buf;
|
||||
if (params.length <= scratch.capacity()) {
|
||||
buf = scratch;
|
||||
buf.clear();
|
||||
buf.limit(params.length);
|
||||
} else {
|
||||
buf = BufferUtils.createDoubleBuffer(params.length);
|
||||
}
|
||||
glGetDouble(pname, buf);
|
||||
buf.position(0);
|
||||
buf.get(params);
|
||||
}
|
||||
|
||||
private static void widenFromFloat(int pname, DoubleBuffer params, int count) {
|
||||
final FloatBuffer scratch = ctx().queryScratch;
|
||||
scratch.clear();
|
||||
glGetFloat(pname, scratch);
|
||||
final int pos = params.position();
|
||||
for (int i = 0; i < count; i++) {
|
||||
params.put(pos + i, scratch.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public static int glGetError() {
|
||||
rejectExitCapture();
|
||||
if (!RENDER_BACKEND.hasContext()) return 0;
|
||||
if (initConfig.isNoErrorChecks()) return 0;
|
||||
return RENDER_BACKEND.getError();
|
||||
}
|
||||
|
||||
public static void checkGLError() {
|
||||
final int error = glGetError();
|
||||
if (error != GL11.GL_NO_ERROR) GLErrorReporter.reportError(error);
|
||||
}
|
||||
|
||||
public static String glGetString(int pname) {
|
||||
rejectExitCapture();
|
||||
if (!RENDER_BACKEND.hasContext()) return "no valid GL/render context";
|
||||
return RENDER_BACKEND.getString(pname);
|
||||
}
|
||||
|
||||
public static String glGetStringi(int name, int index) {
|
||||
rejectExitCapture();
|
||||
if (!RENDER_BACKEND.hasContext()) return "no valid GL/render context";
|
||||
return RENDER_BACKEND.getStringi(name, index);
|
||||
}
|
||||
public static boolean glIsQuery(int query) { rejectExitCapture(); return RENDER_BACKEND.isQuery(query); }
|
||||
|
||||
public static void glGenQueries(IntBuffer ids) {
|
||||
requireContext("glGenQueries");
|
||||
RENDER_BACKEND.genQueries(ids);
|
||||
}
|
||||
public static int glGenQueries() {
|
||||
requireContext("glGenQueries");
|
||||
return RENDER_BACKEND.genQueries();
|
||||
}
|
||||
public static void glDeleteQueries(int id) { rejectExitCapture(); RENDER_BACKEND.deleteQueries(id); }
|
||||
public static void glBeginQuery(int target, int id) { rejectExitCapture(); RENDER_BACKEND.beginQuery(target, id); }
|
||||
public static void glEndQuery(int target) { rejectExitCapture(); RENDER_BACKEND.endQuery(target); }
|
||||
public static void glGetQueryObjectui(int id, int pname, IntBuffer params) { rejectExitCapture(); RENDER_BACKEND.getQueryObjectui(id, pname, params); }
|
||||
public static int glGetQueryObjecti(int id, int pname) { rejectExitCapture(); return RENDER_BACKEND.getQueryObjecti(id, pname); }
|
||||
public static void glQueryCounter(int id, int target) { rejectExitCapture(); RENDER_BACKEND.queryCounter(id, target); }
|
||||
public static long glGetQueryObjectui64(int id, int pname) { rejectExitCapture(); return RENDER_BACKEND.getQueryObjectui64(id, pname); }
|
||||
|
||||
public static void glGetInteger(int pname, int[] params) {
|
||||
rejectExitCapture();
|
||||
if (!isCachingEnabled() || params.length == 0) {
|
||||
RENDER_BACKEND.getInteger(pname, params);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (pname) {
|
||||
case GL11.GL_VIEWPORT -> {
|
||||
if (params.length < 4) {
|
||||
RENDER_BACKEND.getInteger(pname, params);
|
||||
} else {
|
||||
ctx().viewportState.get(params);
|
||||
}
|
||||
}
|
||||
case GL11.GL_SCISSOR_BOX -> {
|
||||
if (params.length < 4) {
|
||||
RENDER_BACKEND.getInteger(pname, params);
|
||||
} else {
|
||||
ctx().scissorState.get(params);
|
||||
}
|
||||
}
|
||||
case GL11.GL_POLYGON_MODE -> {
|
||||
final PolygonState polygon = ctx().polygonState;
|
||||
params[0] = polygon.getFrontMode();
|
||||
if (params.length > 1) params[1] = polygon.getBackMode();
|
||||
}
|
||||
default -> {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!HAS_MULTIPLE_SET.contains(pname)) {
|
||||
params[0] = glGetInteger(glCtx, pname);
|
||||
} else if (!LegacyQueries.getIntegerv(glCtx, pname, params)) {
|
||||
RENDER_BACKEND.getInteger(pname, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int indexedIntegerOrBackend(int pname, int index) {
|
||||
if (pname == GL31.GL_UNIFORM_BUFFER_BINDING) return GLSMBuffers.getIndexedBufferBinding(GL31.GL_UNIFORM_BUFFER, index);
|
||||
if (pname == GL43.GL_SHADER_STORAGE_BUFFER_BINDING) return GLSMBuffers.getIndexedBufferBinding(GL43.GL_SHADER_STORAGE_BUFFER, index);
|
||||
final ImageUnitBinding binding = !isCachingEnabled() ? null : ctx().imageUnits.get(index);
|
||||
if (binding == null) return RENDER_BACKEND.getIntegerIndexed(pname, index);
|
||||
return switch (pname) {
|
||||
case GL42.GL_IMAGE_BINDING_NAME -> binding.getTexture();
|
||||
case GL42.GL_IMAGE_BINDING_LEVEL -> binding.getLevel();
|
||||
case GL42.GL_IMAGE_BINDING_LAYERED -> binding.isLayered() ? GL11.GL_TRUE : GL11.GL_FALSE;
|
||||
case GL42.GL_IMAGE_BINDING_LAYER -> binding.getLayer();
|
||||
case GL42.GL_IMAGE_BINDING_ACCESS -> binding.getAccess();
|
||||
case GL42.GL_IMAGE_BINDING_FORMAT -> binding.getFormat();
|
||||
default -> RENDER_BACKEND.getIntegerIndexed(pname, index);
|
||||
};
|
||||
}
|
||||
|
||||
public static int glGetInteger(int pname, int index) {
|
||||
rejectExitCapture();
|
||||
return indexedIntegerOrBackend(pname, index);
|
||||
}
|
||||
|
||||
public static int glGetIntegeri(int pname, int index) {
|
||||
rejectExitCapture();
|
||||
return indexedIntegerOrBackend(pname, index);
|
||||
}
|
||||
|
||||
public static void glGetIntegeri(int pname, int index, IntBuffer params) {
|
||||
glGetIntegeri_v(pname, index, params);
|
||||
}
|
||||
|
||||
public static void glGetIntegeri_v(int pname, int index, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
params.put(params.position(), indexedIntegerOrBackend(pname, index));
|
||||
}
|
||||
|
||||
public static void glGetBooleani_v(int pname, int index, ByteBuffer params) {
|
||||
rejectExitCapture();
|
||||
params.put(params.position(), (byte) (indexedIntegerOrBackend(pname, index) != 0 ? GL11.GL_TRUE : GL11.GL_FALSE));
|
||||
}
|
||||
|
||||
public static void glGetBooleani(int pname, int index, ByteBuffer params) {
|
||||
glGetBooleani_v(pname, index, params);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,711 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager.RecordMode;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.IntegerStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.LineStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.PointStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.PolygonStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.ScissorStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.ViewPortStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ClipPlaneState;
|
||||
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 java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.LOGGER;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.MAX_CLIP_PLANES;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.guardUnsupportedFFP;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.mod;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMRasterizer {
|
||||
|
||||
private GLSMRasterizer() {}
|
||||
|
||||
static float maxPointSize;
|
||||
|
||||
// Line width range queried at init from GL_ALIASED_LINE_WIDTH_RANGE
|
||||
static float lineWidthMin = 1.0f;
|
||||
static float lineWidthMax = 1.0f;
|
||||
// The driver cannot draw wide lines (Mesa forward-compat, SDL_GPU), so FFP widens them from LineQuads in the vertex shader
|
||||
public static boolean wideLineEmulationEnabled = false;
|
||||
|
||||
public static void glGetClipPlane(int plane, DoubleBuffer equation) {
|
||||
rejectExitCapture();
|
||||
final int index = plane - GL11.GL_CLIP_PLANE0;
|
||||
if (index < 0 || index >= MAX_CLIP_PLANES) return;
|
||||
ctx().clipPlaneState.getEyePlane(index, equation);
|
||||
}
|
||||
|
||||
static void probeLineWidthRange() {
|
||||
final FloatBuffer lwRange = BufferUtils.createFloatBuffer(16);
|
||||
RENDER_BACKEND.getFloat(GL12.GL_ALIASED_LINE_WIDTH_RANGE, lwRange);
|
||||
lineWidthMin = lwRange.get(0);
|
||||
lineWidthMax = lwRange.get(1);
|
||||
final float queriedMax = lineWidthMax;
|
||||
// Probe whether the driver actually accepts the queried max (Mesa forward-compat rejects > 1.0)
|
||||
if (lineWidthMax > 1.0f) {
|
||||
while (RENDER_BACKEND.getError() != GL11.GL_NO_ERROR) {}
|
||||
RENDER_BACKEND.lineWidth(lineWidthMax);
|
||||
if (RENDER_BACKEND.getError() != GL11.GL_NO_ERROR) {
|
||||
// Binary search for the actual accepted max between 1.0 and queriedMax
|
||||
float lo = 1.0f, hi = queriedMax;
|
||||
while (hi - lo > 0.01f) {
|
||||
final float mid = (lo + hi) * 0.5f;
|
||||
while (RENDER_BACKEND.getError() != GL11.GL_NO_ERROR) {}
|
||||
RENDER_BACKEND.lineWidth(mid);
|
||||
if (RENDER_BACKEND.getError() == GL11.GL_NO_ERROR) {
|
||||
lo = mid;
|
||||
} else {
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
lineWidthMax = lo;
|
||||
}
|
||||
RENDER_BACKEND.lineWidth(1.0f);
|
||||
while (RENDER_BACKEND.getError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
wideLineEmulationEnabled = lineWidthMax <= 1.0f;
|
||||
if (wideLineEmulationEnabled) {
|
||||
LOGGER.info("GL line width: aliased range [{}, {}], probe at {} rejected, native [{}, {}], line quads widen ({}, {}]", lineWidthMin, queriedMax, queriedMax, lineWidthMin, lineWidthMax, lineWidthMax, queriedMax);
|
||||
} else {
|
||||
LOGGER.info("GL line width: aliased range [{}, {}], probe at {} accepted, native [{}, {}]", lineWidthMin, queriedMax, queriedMax, lineWidthMin, lineWidthMax);
|
||||
}
|
||||
}
|
||||
|
||||
static void probePointSizeRange(GLContextState glCtx) {
|
||||
final FloatBuffer range = glCtx.queryScratch;
|
||||
range.clear();
|
||||
float smooth = 0.0f;
|
||||
if (!RenderSystem.isGLES()) {
|
||||
RENDER_BACKEND.getFloat(GL11.GL_POINT_SIZE_RANGE, range);
|
||||
smooth = range.get(1);
|
||||
}
|
||||
RENDER_BACKEND.getFloat(GL12.GL_ALIASED_POINT_SIZE_RANGE, range);
|
||||
maxPointSize = Math.max(smooth, range.get(1));
|
||||
}
|
||||
|
||||
public static void enableScissorTest() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_SCISSOR_TEST);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableScissorTest(ctx());
|
||||
}
|
||||
|
||||
static void enableScissorTest(GLContextState glCtx) {
|
||||
glCtx.scissorTest.enable();
|
||||
}
|
||||
|
||||
public static void disableScissorTest() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_SCISSOR_TEST);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableScissorTest(ctx());
|
||||
}
|
||||
|
||||
static void disableScissorTest(GLContextState glCtx) {
|
||||
glCtx.scissorTest.disable();
|
||||
}
|
||||
|
||||
public static void glPointParameterf(int pname, float param) {
|
||||
pointParameter(pname, param, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public static void glPointParameteri(int pname, int param) {
|
||||
pointParameter(pname, param, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
public static void glPointParameter(int pname, FloatBuffer params) {
|
||||
final int pos = params.position();
|
||||
final boolean attenuation = pname == GL14.GL_POINT_DISTANCE_ATTENUATION;
|
||||
pointParameter(pname, params.get(pos), attenuation ? params.get(pos + 1) : 0.0f, attenuation ? params.get(pos + 2) : 0.0f);
|
||||
}
|
||||
|
||||
public static void glPointParameter(int pname, IntBuffer params) {
|
||||
final int pos = params.position();
|
||||
final boolean attenuation = pname == GL14.GL_POINT_DISTANCE_ATTENUATION;
|
||||
pointParameter(pname, params.get(pos), attenuation ? params.get(pos + 1) : 0.0f, attenuation ? params.get(pos + 2) : 0.0f);
|
||||
}
|
||||
|
||||
private static void pointParameter(int pname, float v0, float v1, float v2) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final PointStateStack point = glCtx.pointState;
|
||||
switch (pname) {
|
||||
case GL14.GL_POINT_SIZE_MIN -> {
|
||||
if (!(v0 < 0.0f) && point.getMinSize() != v0) mod(point).setMinSize(v0);
|
||||
}
|
||||
case GL14.GL_POINT_SIZE_MAX -> {
|
||||
if (!(v0 < 0.0f) && point.getMaxSize() != v0) mod(point).setMaxSize(v0);
|
||||
}
|
||||
case GL14.GL_POINT_FADE_THRESHOLD_SIZE -> {
|
||||
if (!(v0 < 0.0f) && point.getFadeThreshold() != v0) {
|
||||
mod(point).setFadeThreshold(v0);
|
||||
RENDER_BACKEND.pointParameterf(pname, v0);
|
||||
}
|
||||
}
|
||||
case GL14.GL_POINT_DISTANCE_ATTENUATION -> {
|
||||
if (point.getAttenuationConstant() == v0 && point.getAttenuationLinear() == v1 && point.getAttenuationQuadratic() == v2) return;
|
||||
mod(point);
|
||||
point.setAttenuationConstant(v0);
|
||||
point.setAttenuationLinear(v1);
|
||||
point.setAttenuationQuadratic(v2);
|
||||
}
|
||||
case GL20.GL_POINT_SPRITE_COORD_ORIGIN -> {
|
||||
final int origin = (int) v0;
|
||||
if ((origin == GL20.GL_LOWER_LEFT || origin == GL20.GL_UPPER_LEFT) && point.getSpriteCoordOrigin() != origin) {
|
||||
mod(point).setSpriteCoordOrigin(origin);
|
||||
RENDER_BACKEND.pointParameteri(pname, origin);
|
||||
}
|
||||
}
|
||||
default -> RENDER_BACKEND.pointParameterf(pname, v0);
|
||||
}
|
||||
}
|
||||
|
||||
static void applyPointState(GLContextState glCtx) {
|
||||
final PointStateStack point = glCtx.pointState;
|
||||
RENDER_BACKEND.pointSize(point.getSize());
|
||||
RENDER_BACKEND.pointParameterf(GL14.GL_POINT_FADE_THRESHOLD_SIZE, point.getFadeThreshold());
|
||||
RENDER_BACKEND.pointParameteri(GL20.GL_POINT_SPRITE_COORD_ORIGIN, point.getSpriteCoordOrigin());
|
||||
}
|
||||
|
||||
private static boolean isLegacyHint(int target) {
|
||||
return switch (target) {
|
||||
case GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_POINT_SMOOTH_HINT, GL11.GL_FOG_HINT, GL14.GL_GENERATE_MIPMAP_HINT -> true;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
static int hintShift(int target) {
|
||||
return switch (target) {
|
||||
case GL11.GL_PERSPECTIVE_CORRECTION_HINT -> 0;
|
||||
case GL11.GL_POINT_SMOOTH_HINT -> 2;
|
||||
case GL11.GL_LINE_SMOOTH_HINT -> 4;
|
||||
case GL11.GL_POLYGON_SMOOTH_HINT -> 6;
|
||||
case GL11.GL_FOG_HINT -> 8;
|
||||
case GL13.GL_TEXTURE_COMPRESSION_HINT -> 10;
|
||||
case GL14.GL_GENERATE_MIPMAP_HINT -> 12;
|
||||
case GL20.GL_FRAGMENT_SHADER_DERIVATIVE_HINT -> 14;
|
||||
default -> -1;
|
||||
};
|
||||
}
|
||||
|
||||
static int hintMode(int packed, int shift) {
|
||||
return switch (packed >>> shift & 3) {
|
||||
case 1 -> GL11.GL_FASTEST;
|
||||
case 2 -> GL11.GL_NICEST;
|
||||
default -> GL11.GL_DONT_CARE;
|
||||
};
|
||||
}
|
||||
|
||||
private static final int[] DRIVER_HINTS = {
|
||||
GL11.GL_LINE_SMOOTH_HINT, GL11.GL_POLYGON_SMOOTH_HINT, GL13.GL_TEXTURE_COMPRESSION_HINT, GL20.GL_FRAGMENT_SHADER_DERIVATIVE_HINT
|
||||
};
|
||||
|
||||
static void applyHintState(GLContextState glCtx) {
|
||||
final int packed = glCtx.hintState.getValue();
|
||||
for (final int target : DRIVER_HINTS) {
|
||||
RENDER_BACKEND.hint(target, hintMode(packed, hintShift(target)));
|
||||
}
|
||||
}
|
||||
|
||||
public static void enableCull() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordEnable(GL11.GL_CULL_FACE);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
enableCull(ctx());
|
||||
}
|
||||
|
||||
static void enableCull(GLContextState glCtx) {
|
||||
glCtx.cullState.enable();
|
||||
}
|
||||
|
||||
public static void disableCull() {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordDisable(GL11.GL_CULL_FACE);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
disableCull(ctx());
|
||||
}
|
||||
|
||||
static void disableCull(GLContextState glCtx) {
|
||||
glCtx.cullState.disable();
|
||||
}
|
||||
|
||||
public static void glShadeModel(int mode) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.SHADE_MODEL);
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
DisplayListManager.recordShadeModel(mode);
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final int oldValue = glCtx.shadeModelState.getValue();
|
||||
final boolean needsUpdate = !caching || oldValue != mode;
|
||||
|
||||
if (needsUpdate) {
|
||||
mod(glCtx.shadeModelState).setValue(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glViewport(int x, int y, int width, int height) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordViewport(x, y, width, height);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
RENDER_BACKEND.viewport(x, y, width, height);
|
||||
// Only update cached state when caching is enabled
|
||||
if (isCachingEnabled()) {
|
||||
mod(ctx().viewportState).setViewPort(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLineWidth(float width) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLineWidth(width);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.lineState.getWidth() != width) {
|
||||
mod(glCtx.lineState).setWidth(width);
|
||||
RENDER_BACKEND.lineWidth(Math.clamp(width, lineWidthMin, lineWidthMax));
|
||||
}
|
||||
}
|
||||
|
||||
public static void glCullFace(int mode) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.CULL_FACE);
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
DisplayListManager.recordCullFace(mode);
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.polygonState.getCullFaceMode() != mode) {
|
||||
mod(glCtx.polygonState).setCullFaceMode(mode);
|
||||
RENDER_BACKEND.cullFace(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glFrontFace(int mode) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.FRONT_FACE);
|
||||
final RecordMode recordMode = DisplayListManager.getRecordMode();
|
||||
if (recordMode != RecordMode.NONE) {
|
||||
DisplayListManager.recordFrontFace(mode);
|
||||
if (recordMode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.polygonState.getFrontFace() != mode) {
|
||||
mod(glCtx.polygonState).setFrontFace(mode);
|
||||
RENDER_BACKEND.frontFace(mode);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glHint(int target, int hint) {
|
||||
rejectExitCapture();
|
||||
if (hint != GL11.GL_NICEST && hint != GL11.GL_FASTEST && hint != GL11.GL_DONT_CARE) {
|
||||
return;
|
||||
}
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordHint(target, hint);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final int shift = hintShift(target);
|
||||
if (shift >= 0) {
|
||||
final IntegerStateStack hints = ctx().hintState;
|
||||
final int code = hint == GL11.GL_FASTEST ? 1 : hint == GL11.GL_NICEST ? 2 : 0;
|
||||
final int packed = hints.getValue() & ~(3 << shift) | code << shift;
|
||||
if (packed != hints.getValue()) mod(hints).setValue(packed);
|
||||
}
|
||||
if (!isLegacyHint(target)) {
|
||||
RENDER_BACKEND.hint(target, hint);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLineStipple(int factor, short pattern) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordLineStipple(factor, pattern);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mod(glCtx.lineState);
|
||||
glCtx.lineState.setStippleFactor(factor);
|
||||
glCtx.lineState.setStipplePattern(pattern);
|
||||
}
|
||||
|
||||
public static void glPointSize(float size) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordPointSize(size);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.pointState.getSize() != size) {
|
||||
mod(glCtx.pointState).setSize(size);
|
||||
RENDER_BACKEND.pointSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glPolygonMode(int face, int polygonMode) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordPolygonMode(face, polygonMode);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Track front/back separately in cache (Mesa compat semantics), but always issue GL_FRONT_AND_BACK to the driver (core profile constraint).
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean front = face != GL11.GL_BACK;
|
||||
final boolean back = face != GL11.GL_FRONT;
|
||||
final boolean needsUpdate = !caching
|
||||
|| (front && glCtx.polygonState.getFrontMode() != polygonMode)
|
||||
|| (back && glCtx.polygonState.getBackMode() != polygonMode);
|
||||
if (!needsUpdate) return;
|
||||
beforeUncapturedStateChange();
|
||||
if (caching) {
|
||||
mod(glCtx.polygonState);
|
||||
if (front) glCtx.polygonState.setFrontMode(polygonMode);
|
||||
if (back) glCtx.polygonState.setBackMode(polygonMode);
|
||||
}
|
||||
RENDER_BACKEND.polygonMode(GL11.GL_FRONT_AND_BACK, polygonMode);
|
||||
}
|
||||
|
||||
public static void glPolygonOffset(float factor, float units) {
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.OFFSET_VALUES);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordPolygonOffset(factor, units);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
|
||||
if (!caching || glCtx.polygonState.getOffsetFactor() != factor || glCtx.polygonState.getOffsetUnits() != units || glCtx.polygonState.getOffsetClamp() != 0.0f) {
|
||||
mod(glCtx.polygonState);
|
||||
glCtx.polygonState.setOffsetFactor(factor);
|
||||
glCtx.polygonState.setOffsetUnits(units);
|
||||
glCtx.polygonState.setOffsetClamp(0.0f);
|
||||
RENDER_BACKEND.polygonOffset(factor, units);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glPolygonOffsetClamp(float factor, float units, float clamp) {
|
||||
if (clamp == 0.0f) {
|
||||
glPolygonOffset(factor, units);
|
||||
return;
|
||||
}
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw DisplayListManager.unsupportedInList("glPolygonOffsetClamp");
|
||||
}
|
||||
final GLContextState glCtx = ctx();
|
||||
glCtx.exitCapture.write(ExitStateCapture.OFFSET_VALUES);
|
||||
final boolean caching = isCachingEnabled();
|
||||
if (!caching || glCtx.polygonState.getOffsetFactor() != factor || glCtx.polygonState.getOffsetUnits() != units || glCtx.polygonState.getOffsetClamp() != clamp) {
|
||||
mod(glCtx.polygonState);
|
||||
glCtx.polygonState.setOffsetFactor(factor);
|
||||
glCtx.polygonState.setOffsetUnits(units);
|
||||
glCtx.polygonState.setOffsetClamp(clamp);
|
||||
RENDER_BACKEND.polygonOffsetClamp(factor, units, clamp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glScissor(int x, int y, int width, int height) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordScissor(x, y, width, height);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
RENDER_BACKEND.scissor(x, y, width, height);
|
||||
if (isCachingEnabled()) {
|
||||
mod(ctx().scissorState).setScissor(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glClipPlane(int plane, DoubleBuffer equation) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (DisplayListManager.isRecording()) {
|
||||
final int pos = equation.position();
|
||||
DisplayListManager.recordClipPlane(plane, equation.get(pos), equation.get(pos + 1), equation.get(pos + 2), equation.get(pos + 3));
|
||||
return;
|
||||
}
|
||||
final int index = plane - GL11.GL_CLIP_PLANE0;
|
||||
if (index < 0 || index >= MAX_CLIP_PLANES) return;
|
||||
final int pos = equation.position();
|
||||
beforeUncapturedStateChange();
|
||||
glCtx.clipPlaneState.setPlane(index, equation.get(pos), equation.get(pos + 1), equation.get(pos + 2), equation.get(pos + 3), glCtx.modelViewMatrix);
|
||||
glCtx.clipPlaneGeneration++;
|
||||
}
|
||||
|
||||
/** Returns true if any GL_CLIP_PLANE0..7 is currently enabled. */
|
||||
public static boolean anyClipPlaneEnabled() {
|
||||
return anyClipPlaneEnabled(ctx());
|
||||
}
|
||||
|
||||
public static boolean anyClipPlaneEnabled(GLContextState glCtx) {
|
||||
return glCtx.clipPlaneEnabledMask != 0;
|
||||
}
|
||||
|
||||
public static boolean clipEmulationActive() {
|
||||
return RenderSystem.isClipDistanceEmulated() && anyClipPlaneEnabled();
|
||||
}
|
||||
|
||||
public static boolean clipEmulationActive(GLContextState glCtx) {
|
||||
return RenderSystem.isClipDistanceEmulated() && anyClipPlaneEnabled(glCtx);
|
||||
}
|
||||
|
||||
public static void glSampleCoverage(float value, boolean invert) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw DisplayListManager.unsupportedInList("glSampleCoverage");
|
||||
}
|
||||
beforeUncapturedStateChange();
|
||||
RENDER_BACKEND.sampleCoverage(value, invert);
|
||||
}
|
||||
|
||||
public static void glPolygonStipple(ByteBuffer pattern) {
|
||||
guardUnsupportedFFP("glPolygonStipple", "glPolygonStipple is not available in GL 3.3 core profile.");
|
||||
}
|
||||
|
||||
public static IntegerStateStack getShadeModelState() {
|
||||
return ctx().shadeModelState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getScissorTest() {
|
||||
return ctx().scissorTest;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getCullState() {
|
||||
return ctx().cullState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getDitherState() {
|
||||
return ctx().ditherState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getLineSmoothState() {
|
||||
return ctx().lineSmoothState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getLineStippleState() {
|
||||
return ctx().lineStippleState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getPointSmoothState() {
|
||||
return ctx().pointSmoothState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getPolygonSmoothState() {
|
||||
return ctx().polygonSmoothState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getPolygonStippleState() {
|
||||
return ctx().polygonStippleState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMultisampleState() {
|
||||
return ctx().multisampleState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getSampleAlphaToCoverageState() {
|
||||
return ctx().sampleAlphaToCoverageState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getSampleAlphaToOneState() {
|
||||
return ctx().sampleAlphaToOneState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getSampleCoverageState() {
|
||||
return ctx().sampleCoverageState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getPolygonOffsetPointState() {
|
||||
return ctx().polygonOffsetPointState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getPolygonOffsetLineState() {
|
||||
return ctx().polygonOffsetLineState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getPolygonOffsetFillState() {
|
||||
return ctx().polygonOffsetFillState;
|
||||
}
|
||||
|
||||
public static LineStateStack getLineState() {
|
||||
return ctx().lineState;
|
||||
}
|
||||
|
||||
public static PointStateStack getPointState() {
|
||||
return ctx().pointState;
|
||||
}
|
||||
|
||||
public static IntegerStateStack getHintState() {
|
||||
return ctx().hintState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getPointSpriteState() {
|
||||
return ctx().pointSpriteState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getEdgeFlagState() {
|
||||
return ctx().edgeFlagState;
|
||||
}
|
||||
|
||||
public static PolygonStateStack getPolygonState() {
|
||||
return ctx().polygonState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getAutoNormalState() {
|
||||
return ctx().autoNormalState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1Color4State() {
|
||||
return ctx().map1Color4State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1IndexState() {
|
||||
return ctx().map1IndexState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1NormalState() {
|
||||
return ctx().map1NormalState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1TextureCoord1State() {
|
||||
return ctx().map1TextureCoord1State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1TextureCoord2State() {
|
||||
return ctx().map1TextureCoord2State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1TextureCoord3State() {
|
||||
return ctx().map1TextureCoord3State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1TextureCoord4State() {
|
||||
return ctx().map1TextureCoord4State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1Vertex3State() {
|
||||
return ctx().map1Vertex3State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap1Vertex4State() {
|
||||
return ctx().map1Vertex4State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2Color4State() {
|
||||
return ctx().map2Color4State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2IndexState() {
|
||||
return ctx().map2IndexState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2NormalState() {
|
||||
return ctx().map2NormalState;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2TextureCoord1State() {
|
||||
return ctx().map2TextureCoord1State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2TextureCoord2State() {
|
||||
return ctx().map2TextureCoord2State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2TextureCoord3State() {
|
||||
return ctx().map2TextureCoord3State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2TextureCoord4State() {
|
||||
return ctx().map2TextureCoord4State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2Vertex3State() {
|
||||
return ctx().map2Vertex3State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack getMap2Vertex4State() {
|
||||
return ctx().map2Vertex4State;
|
||||
}
|
||||
|
||||
public static BooleanStateStack[] getClipPlaneStates() {
|
||||
return ctx().clipPlaneStates;
|
||||
}
|
||||
|
||||
public static ClipPlaneState getClipPlaneState() {
|
||||
return ctx().clipPlaneState;
|
||||
}
|
||||
|
||||
public static ViewPortStateStack getViewportState() {
|
||||
return ctx().viewportState;
|
||||
}
|
||||
|
||||
public static ScissorStateStack getScissorState() {
|
||||
return ctx().scissorState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.beforeUncapturedStateChange;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.guardUnsupportedFFP;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.isCachingEnabled;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
|
||||
public final class GLSMTexEnvGen {
|
||||
|
||||
private GLSMTexEnvGen() {}
|
||||
|
||||
public static void glTexEnvi(int target, int pname, int param) {
|
||||
handleTexEnvScalar(target, pname, param);
|
||||
}
|
||||
|
||||
public static void glTexEnvf(int target, int pname, float param) {
|
||||
handleTexEnvScalar(target, pname, param);
|
||||
}
|
||||
|
||||
public static void glTexEnv(int target, int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (target == GL11.GL_TEXTURE_ENV && pname == GL11.GL_TEXTURE_ENV_COLOR && params.remaining() >= 4) {
|
||||
beforeUncapturedStateChange();
|
||||
final int pos = params.position();
|
||||
final var envState = glCtx.textures.getTexEnvState(glCtx.activeTextureUnit.getValue());
|
||||
envState.beforeModify();
|
||||
envState.envColorR = params.get(pos);
|
||||
envState.envColorG = params.get(pos + 1);
|
||||
envState.envColorB = params.get(pos + 2);
|
||||
envState.envColorA = params.get(pos + 3);
|
||||
glCtx.fragmentGeneration++;
|
||||
return;
|
||||
}
|
||||
if (target == GL14.GL_TEXTURE_FILTER_CONTROL) {
|
||||
guardUnsupportedFFP(
|
||||
"glTexEnv",
|
||||
"LOD bias via buffer glTexEnv is not supported; use glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, value) instead.");
|
||||
return;
|
||||
}
|
||||
// Silently ignore other buffer glTexEnv calls (some mods pass combine params via buffers)
|
||||
}
|
||||
|
||||
public static void glTexEnv(int target, int pname, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
if (target == GL11.GL_TEXTURE_ENV) {
|
||||
handleTexEnvScalar(target, pname, (float) params.get(params.position()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scalar glTexEnvi/glTexEnvf dispatch. glTexEnv is removed in core profile. GL_TEXTURE_FILTER_CONTROL (LOD bias) is remapped to glTexParameterf. All
|
||||
* GL_TEXTURE_ENV parameters including GL_COMBINE sub-params are tracked in per-unit TexEnvState.
|
||||
*/
|
||||
private static void handleTexEnvScalar(int target, int pname, float param) {
|
||||
beforeUncapturedStateChange();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (target == GL14.GL_TEXTURE_FILTER_CONTROL) {
|
||||
// LOD bias via legacy glTexEnv path - remap to core-profile glTexParameterf
|
||||
GLSMTextures.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, param);
|
||||
return;
|
||||
}
|
||||
if (target != GL11.GL_TEXTURE_ENV) return;
|
||||
|
||||
final var envState = glCtx.textures.getTexEnvState(glCtx.activeTextureUnit.getValue());
|
||||
envState.beforeModify();
|
||||
final int iparam = (int) param;
|
||||
|
||||
switch (pname) {
|
||||
case GL11.GL_TEXTURE_ENV_MODE -> {
|
||||
envState.mode = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_COMBINE_RGB -> {
|
||||
envState.combineRgb = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_COMBINE_ALPHA -> {
|
||||
envState.combineAlpha = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_SOURCE0_RGB -> {
|
||||
envState.sourceRgb[0] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_SOURCE1_RGB -> {
|
||||
envState.sourceRgb[1] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_SOURCE2_RGB -> {
|
||||
envState.sourceRgb[2] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_SOURCE0_ALPHA -> {
|
||||
envState.sourceAlpha[0] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_SOURCE1_ALPHA -> {
|
||||
envState.sourceAlpha[1] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_SOURCE2_ALPHA -> {
|
||||
envState.sourceAlpha[2] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_OPERAND0_RGB -> {
|
||||
envState.operandRgb[0] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_OPERAND1_RGB -> {
|
||||
envState.operandRgb[1] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_OPERAND2_RGB -> {
|
||||
envState.operandRgb[2] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_OPERAND0_ALPHA -> {
|
||||
envState.operandAlpha[0] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_OPERAND1_ALPHA -> {
|
||||
envState.operandAlpha[1] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_OPERAND2_ALPHA -> {
|
||||
envState.operandAlpha[2] = iparam;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL13.GL_RGB_SCALE -> {
|
||||
envState.scaleRgb = param;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
case GL11.GL_ALPHA_SCALE -> {
|
||||
envState.scaleAlpha = param;
|
||||
glCtx.fragmentGeneration++;
|
||||
}
|
||||
// Silently ignore unknown pname - other mods may pass unrecognized params
|
||||
}
|
||||
}
|
||||
|
||||
public static float glGetTexEnvf(int target, int pname) {
|
||||
return (float) glGetTexEnvi(target, pname);
|
||||
}
|
||||
|
||||
public static int glGetTexEnvi(int target, int pname) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (target != GL11.GL_TEXTURE_ENV) return 0;
|
||||
|
||||
final var envState = glCtx.textures.getTexEnvState(glCtx.activeTextureUnit.getValue());
|
||||
return switch (pname) {
|
||||
case GL11.GL_TEXTURE_ENV_MODE -> envState.mode;
|
||||
case GL13.GL_COMBINE_RGB -> envState.combineRgb;
|
||||
case GL13.GL_COMBINE_ALPHA -> envState.combineAlpha;
|
||||
case GL13.GL_SOURCE0_RGB -> envState.sourceRgb[0];
|
||||
case GL13.GL_SOURCE1_RGB -> envState.sourceRgb[1];
|
||||
case GL13.GL_SOURCE2_RGB -> envState.sourceRgb[2];
|
||||
case GL13.GL_SOURCE0_ALPHA -> envState.sourceAlpha[0];
|
||||
case GL13.GL_SOURCE1_ALPHA -> envState.sourceAlpha[1];
|
||||
case GL13.GL_SOURCE2_ALPHA -> envState.sourceAlpha[2];
|
||||
case GL13.GL_OPERAND0_RGB -> envState.operandRgb[0];
|
||||
case GL13.GL_OPERAND1_RGB -> envState.operandRgb[1];
|
||||
case GL13.GL_OPERAND2_RGB -> envState.operandRgb[2];
|
||||
case GL13.GL_OPERAND0_ALPHA -> envState.operandAlpha[0];
|
||||
case GL13.GL_OPERAND1_ALPHA -> envState.operandAlpha[1];
|
||||
case GL13.GL_OPERAND2_ALPHA -> envState.operandAlpha[2];
|
||||
case GL13.GL_RGB_SCALE -> (int) envState.scaleRgb;
|
||||
case GL11.GL_ALPHA_SCALE -> (int) envState.scaleAlpha;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static void glGetTexEnv(int target, int pname, IntBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (target != GL11.GL_TEXTURE_ENV) return;
|
||||
if (pname == GL11.GL_TEXTURE_ENV_COLOR) {
|
||||
final var envState = glCtx.textures.getTexEnvState(glCtx.activeTextureUnit.getValue());
|
||||
params.put(params.position(), (int) (envState.envColorR * 2147483647.0f));
|
||||
params.put(params.position() + 1, (int) (envState.envColorG * 2147483647.0f));
|
||||
params.put(params.position() + 2, (int) (envState.envColorB * 2147483647.0f));
|
||||
params.put(params.position() + 3, (int) (envState.envColorA * 2147483647.0f));
|
||||
} else {
|
||||
params.put(params.position(), glGetTexEnvi(target, pname));
|
||||
}
|
||||
}
|
||||
|
||||
public static void glGetTexEnv(int target, int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (target != GL11.GL_TEXTURE_ENV) return;
|
||||
if (pname == GL11.GL_TEXTURE_ENV_COLOR) {
|
||||
final var envState = glCtx.textures.getTexEnvState(glCtx.activeTextureUnit.getValue());
|
||||
params.put(params.position(), envState.envColorR);
|
||||
params.put(params.position() + 1, envState.envColorG);
|
||||
params.put(params.position() + 2, envState.envColorB);
|
||||
params.put(params.position() + 3, envState.envColorA);
|
||||
} else {
|
||||
params.put(params.position(), (float) glGetTexEnvi(target, pname));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void glTexGeni(int coord, int pname, int param) {
|
||||
beforeUncapturedStateChange();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) return;
|
||||
if (pname == GL11.GL_TEXTURE_GEN_MODE) {
|
||||
final int unit = glCtx.activeTextureUnit.getValue();
|
||||
glCtx.textures.getTexGenState(unit).setMode(coord, param);
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static void glTexGenf(int coord, int pname, float param) {
|
||||
// Single-float form only valid for GL_TEXTURE_GEN_MODE
|
||||
glTexGeni(coord, pname, (int) param);
|
||||
}
|
||||
|
||||
public static void glTexGend(int coord, int pname, double param) {
|
||||
glTexGeni(coord, pname, (int) param);
|
||||
}
|
||||
|
||||
public static void glTexGen(int coord, int pname, FloatBuffer params) {
|
||||
beforeUncapturedStateChange();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) return;
|
||||
final int unit = glCtx.activeTextureUnit.getValue();
|
||||
final var texGenState = glCtx.textures.getTexGenState(unit);
|
||||
final int pos = params.position();
|
||||
switch (pname) {
|
||||
case GL11.GL_TEXTURE_GEN_MODE -> {
|
||||
texGenState.setMode(coord, (int) params.get(pos));
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
case GL11.GL_OBJECT_PLANE -> {
|
||||
glCtx.texGenTempPlane[0] = params.get(pos);
|
||||
glCtx.texGenTempPlane[1] = params.get(pos + 1);
|
||||
glCtx.texGenTempPlane[2] = params.get(pos + 2);
|
||||
glCtx.texGenTempPlane[3] = params.get(pos + 3);
|
||||
texGenState.setObjectPlane(coord, glCtx.texGenTempPlane);
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
case GL11.GL_EYE_PLANE -> {
|
||||
glCtx.texGenTempPlane[0] = params.get(pos);
|
||||
glCtx.texGenTempPlane[1] = params.get(pos + 1);
|
||||
glCtx.texGenTempPlane[2] = params.get(pos + 2);
|
||||
glCtx.texGenTempPlane[3] = params.get(pos + 3);
|
||||
texGenState.setEyePlane(coord, glCtx.texGenTempPlane, glCtx.modelViewMatrix);
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glTexGen(int coord, int pname, DoubleBuffer params) {
|
||||
beforeUncapturedStateChange();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) return;
|
||||
final int pos = params.position();
|
||||
glCtx.texGenTempPlane[0] = (float) params.get(pos);
|
||||
glCtx.texGenTempPlane[1] = (float) params.get(pos + 1);
|
||||
glCtx.texGenTempPlane[2] = (float) params.get(pos + 2);
|
||||
glCtx.texGenTempPlane[3] = (float) params.get(pos + 3);
|
||||
final int unit = glCtx.activeTextureUnit.getValue();
|
||||
final var texGenState = glCtx.textures.getTexGenState(unit);
|
||||
switch (pname) {
|
||||
case GL11.GL_TEXTURE_GEN_MODE -> {
|
||||
texGenState.setMode(coord, (int) params.get(pos));
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
case GL11.GL_OBJECT_PLANE -> {
|
||||
texGenState.setObjectPlane(coord, glCtx.texGenTempPlane);
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
case GL11.GL_EYE_PLANE -> {
|
||||
texGenState.setEyePlane(coord, glCtx.texGenTempPlane, glCtx.modelViewMatrix);
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void glTexGen(int coord, int pname, IntBuffer params) {
|
||||
beforeUncapturedStateChange();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (!isCachingEnabled()) return;
|
||||
if (pname == GL11.GL_TEXTURE_GEN_MODE) {
|
||||
final int unit = glCtx.activeTextureUnit.getValue();
|
||||
glCtx.textures.getTexGenState(unit).setMode(coord, params.get(params.position()));
|
||||
glCtx.texGenGeneration++;
|
||||
}
|
||||
}
|
||||
|
||||
public static int glGetTexGeni(int coord, int pname) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (pname == GL11.GL_TEXTURE_GEN_MODE) {
|
||||
return glCtx.textures.getTexGenState(glCtx.activeTextureUnit.getValue()).getMode(coord);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static float glGetTexGenf(int coord, int pname) {
|
||||
return (float) glGetTexGeni(coord, pname);
|
||||
}
|
||||
|
||||
public static double glGetTexGend(int coord, int pname) {
|
||||
return glGetTexGeni(coord, pname);
|
||||
}
|
||||
|
||||
public static void glGetTexGen(int coord, int pname, IntBuffer params) {
|
||||
if (pname == GL11.GL_TEXTURE_GEN_MODE) {
|
||||
params.put(params.position(), glGetTexGeni(coord, pname));
|
||||
}
|
||||
}
|
||||
|
||||
public static void glGetTexGen(int coord, int pname, FloatBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final var state = glCtx.textures.getTexGenState(glCtx.activeTextureUnit.getValue());
|
||||
if (pname == GL11.GL_TEXTURE_GEN_MODE) {
|
||||
params.put(params.position(), (float) state.getMode(coord));
|
||||
} else if (pname == GL11.GL_OBJECT_PLANE) {
|
||||
final float[] plane = state.getObjectPlane(coord);
|
||||
params.put(params.position(), plane[0]);
|
||||
params.put(params.position() + 1, plane[1]);
|
||||
params.put(params.position() + 2, plane[2]);
|
||||
params.put(params.position() + 3, plane[3]);
|
||||
} else if (pname == GL11.GL_EYE_PLANE) {
|
||||
final float[] plane = state.getEyePlane(coord);
|
||||
params.put(params.position(), plane[0]);
|
||||
params.put(params.position() + 1, plane[1]);
|
||||
params.put(params.position() + 2, plane[2]);
|
||||
params.put(params.position() + 3, plane[3]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glGetTexGen(int coord, int pname, DoubleBuffer params) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final var state = glCtx.textures.getTexGenState(glCtx.activeTextureUnit.getValue());
|
||||
if (pname == GL11.GL_TEXTURE_GEN_MODE) {
|
||||
params.put(params.position(), state.getMode(coord));
|
||||
} else if (pname == GL11.GL_OBJECT_PLANE) {
|
||||
final float[] plane = state.getObjectPlane(coord);
|
||||
params.put(params.position(), plane[0]);
|
||||
params.put(params.position() + 1, plane[1]);
|
||||
params.put(params.position() + 2, plane[2]);
|
||||
params.put(params.position() + 3, plane[3]);
|
||||
} else if (pname == GL11.GL_EYE_PLANE) {
|
||||
final float[] plane = state.getEyePlane(coord);
|
||||
params.put(params.position(), plane[0]);
|
||||
params.put(params.position() + 1, plane[1]);
|
||||
params.put(params.position() + 2, plane[2]);
|
||||
params.put(params.position() + 3, plane[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.profiling.Tracy;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.TextureBindingStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ImageUnitBinding;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureTargets;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2LongMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2LongMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2LongOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.EXTTextureFilterAnisotropic;
|
||||
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.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
import org.lwjgl.opengl.GL42;
|
||||
import org.lwjgl.opengl.GL43;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.acquireDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.drawableContextStates;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.primaryContext;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.releaseDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.splashComplete;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMTextureLifetime {
|
||||
|
||||
private GLSMTextureLifetime() {}
|
||||
|
||||
// Deferred texture deletion: names kept valid until glGenTextures recycles them.
|
||||
// Emulates Mesa/compat-profile behavior where delete-then-bind doesn't error.
|
||||
private static final Int2LongOpenHashMap deferredDeleteTextures = new Int2LongOpenHashMap();
|
||||
private static final long DEFERRED_ABSENT = Long.MIN_VALUE;
|
||||
private static final long DEFERRED_ATTACHED = -1;
|
||||
private static final long DEFERRED_RELEASED = -2;
|
||||
private static final int RELEASE_DELAY_FRAMES = 3;
|
||||
private static long frameIndex;
|
||||
private static long nextReleaseFrame = Long.MAX_VALUE;
|
||||
private static final Int2IntOpenHashMap non2DTextureTargets = new Int2IntOpenHashMap();
|
||||
private static final Int2IntOpenHashMap textureFramebufferRefs = new Int2IntOpenHashMap();
|
||||
private static final FloatBuffer TRANSPARENT_BLACK = BufferUtils.createFloatBuffer(4);
|
||||
private static final Tracy.ZoneId Z_TEX_RELEASE_STORAGE = Tracy.zoneId("texReleaseStorage", Tracy.COLOR_FFP);
|
||||
private static final Tracy.ZoneId Z_TEX_RESCUE_RESET = Tracy.zoneId("texRescueReset", Tracy.COLOR_FFP);
|
||||
private static final Tracy.ZoneId Z_TEX_FLUSH_DELETES = Tracy.zoneId("texFlushDeletes", Tracy.COLOR_FFP);
|
||||
static {
|
||||
deferredDeleteTextures.defaultReturnValue(DEFERRED_ABSENT);
|
||||
non2DTextureTargets.defaultReturnValue(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer deleting textures until it has been reclaimed.
|
||||
* Why you might ask? In compat profile if you bind a texture that doesn't exist, ie a deleted texture,
|
||||
* mesa will silently create it for you, in core this is an error. Why would you be binding a deleted texture?
|
||||
* Damned if I know, but vanilla and mods do it... they create one, delete it, and then bind it....
|
||||
* */
|
||||
static void deferDeleteTexture(int id) {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (id == 0) return;
|
||||
|
||||
final int savedUnit = glCtx.activeTextureUnit.getValue();
|
||||
int activeUnit = savedUnit;
|
||||
|
||||
// Unbind from all units that have this texture
|
||||
for (int i = 0; i <= glCtx.maxBoundTextureUnit; i++) {
|
||||
final TextureBindingStack unitBindings = glCtx.textures.getTextureUnitBindings(i);
|
||||
if (unitBindings.getBinding() == id) {
|
||||
if (i != activeUnit) {
|
||||
RENDER_BACKEND.activeTexture(GL13.GL_TEXTURE0 + i);
|
||||
activeUnit = i;
|
||||
}
|
||||
final int unitTarget = unitBindings.getTarget();
|
||||
RENDER_BACKEND.bindTexture(unitTarget == 0 ? GL11.GL_TEXTURE_2D : unitTarget, 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i <= glCtx.maxBoundImageUnit; i++) {
|
||||
final ImageUnitBinding image = glCtx.imageUnits.get(i);
|
||||
if (image != null && image.getTexture() == id) {
|
||||
RENDER_BACKEND.bindImageTexture(i, 0, 0, false, 0, GL15.GL_READ_ONLY, GL30.GL_R8);
|
||||
}
|
||||
}
|
||||
|
||||
if (activeUnit != savedUnit) {
|
||||
RENDER_BACKEND.activeTexture(GL13.GL_TEXTURE0 + savedUnit);
|
||||
}
|
||||
|
||||
final TextureBindingStack savedBindings = glCtx.textures.getTextureUnitBindings(savedUnit);
|
||||
if (!is2D(savedBindings.getTarget()) && previous2D(savedBindings) == id) restoreUnitAfter2DBind(savedBindings, id, id);
|
||||
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
detachFromFramebuffer(glCtx, GL30.GL_DRAW_FRAMEBUFFER, glCtx.drawFramebuffer, id);
|
||||
if (glCtx.readFramebuffer != glCtx.drawFramebuffer) detachFromFramebuffer(glCtx, GL30.GL_READ_FRAMEBUFFER, glCtx.readFramebuffer, id);
|
||||
if (textureFramebufferRefs.get(id) > 0) deferredDeleteTextures.put(id, DEFERRED_ATTACHED);
|
||||
else scheduleRelease(id);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void scheduleRelease(int id) {
|
||||
deferredDeleteTextures.put(id, frameIndex);
|
||||
nextReleaseFrame = Math.min(nextReleaseFrame, frameIndex + RELEASE_DELAY_FRAMES);
|
||||
}
|
||||
|
||||
static final long BIND_REJECTED = Long.MIN_VALUE + 1;
|
||||
|
||||
// Rebinding a deferred-delete texture rescues it (Mesa/compat-profile behavior)
|
||||
static long claimForBind(int texture, int target) {
|
||||
if (texture == 0) return DEFERRED_ABSENT;
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
final long state = deferredDeleteTextures.isEmpty() ? DEFERRED_ABSENT : deferredDeleteTextures.get(texture);
|
||||
if (state == DEFERRED_ABSENT) {
|
||||
recordTarget(texture, target);
|
||||
return DEFERRED_ABSENT;
|
||||
}
|
||||
return non2DTextureTargets.get(texture) == target ? deferredDeleteTextures.remove(texture) : BIND_REJECTED;
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
static void finishRescue(int target, int texture, long claim) {
|
||||
if (claim != DEFERRED_ABSENT) resetRescuedTexture(target, texture, claim);
|
||||
}
|
||||
|
||||
static int targetOf(int texture) {
|
||||
return non2DTextureTargets.get(texture);
|
||||
}
|
||||
|
||||
static boolean isDeferredDelete(int texture) {
|
||||
if (texture == 0 || deferredDeleteTextures.isEmpty()) return false;
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
return deferredDeleteTextures.containsKey(texture);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void onFrameEnd() {
|
||||
frameIndex++;
|
||||
if (!splashComplete || frameIndex < nextReleaseFrame) return;
|
||||
nextReleaseFrame = Long.MAX_VALUE;
|
||||
for (Int2LongMap.Entry entry : Int2LongMaps.fastIterable(deferredDeleteTextures)) {
|
||||
final long since = entry.getLongValue();
|
||||
if (since < 0) continue;
|
||||
if (frameIndex - since < RELEASE_DELAY_FRAMES) {
|
||||
nextReleaseFrame = Math.min(nextReleaseFrame, since + RELEASE_DELAY_FRAMES);
|
||||
continue;
|
||||
}
|
||||
final int id = entry.getIntKey();
|
||||
if (non2DTextureTargets.get(id) == GL11.GL_TEXTURE_2D) releaseStorage2D(id);
|
||||
entry.setValue(DEFERRED_RELEASED);
|
||||
}
|
||||
}
|
||||
|
||||
public static int deferredTexturesAwaitingRelease() {
|
||||
int count = 0;
|
||||
final LongIterator it = deferredDeleteTextures.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
if (it.nextLong() != DEFERRED_RELEASED) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static void releaseStorage2D(int id) {
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_TEX_RELEASE_STORAGE);
|
||||
try {
|
||||
final TextureBindingStack unit = ctx().textures.getTextureUnitBindings(GLSMTextures.getActiveTextureUnit());
|
||||
final int previous2D = previous2D(unit);
|
||||
RENDER_BACKEND.bindTexture(GL11.GL_TEXTURE_2D, id);
|
||||
if (bindTook(GL11.GL_TEXTURE_2D, id)) releaseBoundStorage2D();
|
||||
restoreUnitAfter2DBind(unit, id, previous2D);
|
||||
} finally {
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
}
|
||||
}
|
||||
|
||||
private static void restoreUnitAfter2DBind(TextureBindingStack unit, int deleted, int previous2D) {
|
||||
RENDER_BACKEND.bindTexture(GL11.GL_TEXTURE_2D, previous2D == deleted ? 0 : previous2D);
|
||||
final int target = unit.getTarget();
|
||||
if (is2D(target)) return;
|
||||
RENDER_BACKEND.bindTexture(target, unit.getBinding() == deleted ? 0 : unit.getBinding());
|
||||
}
|
||||
|
||||
static boolean is2D(int target) {
|
||||
return target == 0 || target == GL11.GL_TEXTURE_2D;
|
||||
}
|
||||
|
||||
private static int previous2D(TextureBindingStack unit) {
|
||||
return is2D(unit.getTarget()) ? unit.getBinding() : RENDER_BACKEND.getInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
}
|
||||
|
||||
static void recordTarget(int texture, int target) {
|
||||
if (target != GL11.GL_TEXTURE_2D) non2DTextureTargets.put(texture, target);
|
||||
}
|
||||
|
||||
private static void releaseBoundStorage2D() {
|
||||
if (RenderSystem.supportsTextureStorage() && RENDER_BACKEND.getTexParameteri(GL11.GL_TEXTURE_2D, GL42.GL_TEXTURE_IMMUTABLE_FORMAT) != 0) return;
|
||||
final int size = Math.max(RENDER_BACKEND.getTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH), RENDER_BACKEND.getTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT));
|
||||
final int levels = Math.max(1, 32 - Integer.numberOfLeadingZeros(size));
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
for (int level = 0; level < levels; level++) {
|
||||
RENDER_BACKEND.texImage2D(GL11.GL_TEXTURE_2D, level, GL11.GL_RGBA8, 0, 0, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||
}
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
private static boolean bindTook(int target, int texture) {
|
||||
return RENDER_BACKEND.getInteger(TextureTargets.bindingQuery(target)) == texture;
|
||||
}
|
||||
|
||||
private static void resetRescuedTexture(int target, int texture, long state) {
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_TEX_RESCUE_RESET);
|
||||
try {
|
||||
if (!bindTook(target, texture)) return;
|
||||
if (target == GL11.GL_TEXTURE_2D && state >= 0) releaseBoundStorage2D();
|
||||
if (target == GL31.GL_TEXTURE_BUFFER || target == GL32.GL_TEXTURE_2D_MULTISAMPLE || target == GL32.GL_TEXTURE_2D_MULTISAMPLE_ARRAY) return;
|
||||
final boolean rectangle = target == GL31.GL_TEXTURE_RECTANGLE;
|
||||
final int wrap = rectangle ? GL12.GL_CLAMP_TO_EDGE : GL11.GL_REPEAT;
|
||||
RENDER_BACKEND.texParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, rectangle ? GL11.GL_LINEAR : GL11.GL_NEAREST_MIPMAP_LINEAR);
|
||||
RENDER_BACKEND.texParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
|
||||
RENDER_BACKEND.texParameteri(target, GL11.GL_TEXTURE_WRAP_S, wrap);
|
||||
RENDER_BACKEND.texParameteri(target, GL11.GL_TEXTURE_WRAP_T, wrap);
|
||||
RENDER_BACKEND.texParameteri(target, GL12.GL_TEXTURE_WRAP_R, wrap);
|
||||
RENDER_BACKEND.texParameteri(target, GL12.GL_TEXTURE_BASE_LEVEL, 0);
|
||||
if (!rectangle) RENDER_BACKEND.texParameteri(target, GL12.GL_TEXTURE_MAX_LEVEL, 1000);
|
||||
RENDER_BACKEND.texParameterf(target, GL12.GL_TEXTURE_MIN_LOD, -1000.0f);
|
||||
RENDER_BACKEND.texParameterf(target, GL12.GL_TEXTURE_MAX_LOD, 1000.0f);
|
||||
RENDER_BACKEND.texParameteri(target, GL14.GL_TEXTURE_COMPARE_MODE, GL11.GL_NONE);
|
||||
RENDER_BACKEND.texParameteri(target, GL14.GL_TEXTURE_COMPARE_FUNC, GL11.GL_LEQUAL);
|
||||
RENDER_BACKEND.texParameteri(target, GL33.GL_TEXTURE_SWIZZLE_R, GL11.GL_RED);
|
||||
RENDER_BACKEND.texParameteri(target, GL33.GL_TEXTURE_SWIZZLE_G, GL11.GL_GREEN);
|
||||
RENDER_BACKEND.texParameteri(target, GL33.GL_TEXTURE_SWIZZLE_B, GL11.GL_BLUE);
|
||||
RENDER_BACKEND.texParameteri(target, GL33.GL_TEXTURE_SWIZZLE_A, GL11.GL_ALPHA);
|
||||
if (!RenderSystem.isGLES()) {
|
||||
RENDER_BACKEND.texParameterf(target, GL14.GL_TEXTURE_LOD_BIAS, 0.0f);
|
||||
RENDER_BACKEND.texParameterfv(target, GL11.GL_TEXTURE_BORDER_COLOR, TRANSPARENT_BLACK);
|
||||
}
|
||||
if (RenderSystem.supportsStencilTexturing()) RENDER_BACKEND.texParameteri(target, GL43.GL_DEPTH_STENCIL_TEXTURE_MODE, GL11.GL_DEPTH_COMPONENT);
|
||||
if (RENDER_BACKEND.isAnisotropicSupported()) RENDER_BACKEND.texParameterf(target, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
|
||||
} finally {
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
}
|
||||
}
|
||||
|
||||
/** Flush deferred deletes so the driver can recycle names. */
|
||||
static void flushDeferredTextureDeletes() {
|
||||
if (!splashComplete || deferredDeleteTextures.isEmpty()) return;
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_TEX_FLUSH_DELETES);
|
||||
try {
|
||||
final GLContextState primary = primaryContext();
|
||||
final GLContextState[] drawables = drawableContextStates;
|
||||
final var it = Int2LongMaps.fastIterator(deferredDeleteTextures);
|
||||
while (it.hasNext()) {
|
||||
final Int2LongMap.Entry entry = it.next();
|
||||
if (entry.getLongValue() == DEFERRED_ATTACHED) continue;
|
||||
final int id = entry.getIntKey();
|
||||
it.remove();
|
||||
RENDER_BACKEND.deleteTextures(id);
|
||||
non2DTextureTargets.remove(id);
|
||||
GLSMTextures.clearTextureBindings(primary, id);
|
||||
for (int i = 0; i < drawables.length; i++) {
|
||||
GLSMTextures.clearTextureBindings(drawables[i], id);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
}
|
||||
}
|
||||
|
||||
private static final int DEPTH_SLOT = 16;
|
||||
private static final int STENCIL_SLOT = 17;
|
||||
private static final int FRAMEBUFFER_SLOTS = 18;
|
||||
|
||||
private static int attachmentSlot(int attachment) {
|
||||
return switch (attachment) {
|
||||
case GL30.GL_DEPTH_ATTACHMENT -> DEPTH_SLOT;
|
||||
case GL30.GL_STENCIL_ATTACHMENT -> STENCIL_SLOT;
|
||||
default -> attachment >= GL30.GL_COLOR_ATTACHMENT0 && attachment <= GL30.GL_COLOR_ATTACHMENT15 ? attachment - GL30.GL_COLOR_ATTACHMENT0 : -1;
|
||||
};
|
||||
}
|
||||
|
||||
private static int slotAttachment(int slot) {
|
||||
return switch (slot) {
|
||||
case DEPTH_SLOT -> GL30.GL_DEPTH_ATTACHMENT;
|
||||
case STENCIL_SLOT -> GL30.GL_STENCIL_ATTACHMENT;
|
||||
default -> GL30.GL_COLOR_ATTACHMENT0 + slot;
|
||||
};
|
||||
}
|
||||
|
||||
static boolean beginAttach(int target, int attachment, int texture) {
|
||||
final GLContextState glCtx = ctx();
|
||||
return beginAttach(glCtx, target == GL30.GL_READ_FRAMEBUFFER ? glCtx.readFramebuffer : glCtx.drawFramebuffer, attachment, texture);
|
||||
}
|
||||
|
||||
static boolean beginAttach(GLContextState glCtx, int framebuffer, int attachment, int texture) {
|
||||
if (isDeferredDelete(texture)) return false;
|
||||
TextureInfoCache.INSTANCE.onWrittenOutsideUploads(texture);
|
||||
trackFramebufferAttachment(glCtx, framebuffer, attachment, texture);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void trackFramebufferAttachment(GLContextState glCtx, int framebuffer, int attachment, int texture) {
|
||||
if (framebuffer == 0) return;
|
||||
if (attachment == GL30.GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
trackFramebufferAttachment(glCtx, framebuffer, GL30.GL_DEPTH_ATTACHMENT, texture);
|
||||
trackFramebufferAttachment(glCtx, framebuffer, GL30.GL_STENCIL_ATTACHMENT, texture);
|
||||
return;
|
||||
}
|
||||
final int slot = attachmentSlot(attachment);
|
||||
if (slot < 0) return;
|
||||
int[] slots = glCtx.framebufferTextures.get(framebuffer);
|
||||
if (slots == null) {
|
||||
if (texture == 0) return;
|
||||
slots = new int[FRAMEBUFFER_SLOTS];
|
||||
glCtx.framebufferTextures.put(framebuffer, slots);
|
||||
}
|
||||
setFramebufferSlot(slots, slot, texture);
|
||||
}
|
||||
|
||||
static void setFramebufferSlot(int[] slots, int slot, int texture) {
|
||||
final int previous = slots[slot];
|
||||
if (previous == texture) return;
|
||||
slots[slot] = texture;
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (texture != 0) textureFramebufferRefs.addTo(texture, 1);
|
||||
if (previous != 0 && textureFramebufferRefs.addTo(previous, -1) == 1) {
|
||||
textureFramebufferRefs.remove(previous);
|
||||
if (deferredDeleteTextures.get(previous) == DEFERRED_ATTACHED) scheduleRelease(previous);
|
||||
}
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void detachFromFramebuffer(GLContextState glCtx, int target, int framebuffer, int texture) {
|
||||
final int[] slots = glCtx.framebufferTextures.get(framebuffer);
|
||||
if (slots == null) return;
|
||||
for (int slot = 0; slot < slots.length; slot++) {
|
||||
if (slots[slot] != texture) continue;
|
||||
RENDER_BACKEND.framebufferTexture2D(target, slotAttachment(slot), GL11.GL_TEXTURE_2D, 0, 0);
|
||||
setFramebufferSlot(slots, slot, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,654 @@
|
||||
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.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.acquireDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.ctx;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.rejectExitCapture;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.releaseDrawLock;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.requireContext;
|
||||
import static com.gtnewhorizons.angelica.glsm.GLStateManager.warnOnceTrace;
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
public final class GLSMVertexInput {
|
||||
|
||||
private GLSMVertexInput() {}
|
||||
|
||||
public static int getBoundEBO() {
|
||||
return ctx().vaos.boundEBO;
|
||||
}
|
||||
|
||||
private static int texCoordConventional(GLContextState glCtx) {
|
||||
return VAOManager.CONV_TEX0 + glCtx.clientActiveTextureUnit;
|
||||
}
|
||||
|
||||
static void prepareClientArrays(GLContextState glCtx) {
|
||||
final VAOManager vaos = glCtx.vaos;
|
||||
if (vaos.hasAnyClientSideEnabledAttrib()) {
|
||||
vaos.uploadClientArraysToVBO();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isLegalClientArray(int conv, int size, int type, int stride) {
|
||||
return isLegalPointer(VAOManager.isLegalConventional(conv, size, type), "client-array", "client array", conv, size, type, stride);
|
||||
}
|
||||
|
||||
private static boolean isLegalVertexAttrib(int index, int size, int type, int stride, boolean integer) {
|
||||
return isLegalPointer(VAOManager.isLegalGeneric(index, size, type, integer), "vertex-attrib", "vertex attribute", index, size, type, stride);
|
||||
}
|
||||
|
||||
private static boolean isLegalPointer(boolean legal, String key, String what, int slot, int size, int type, int stride) {
|
||||
if (stride < 0) warnOnceTrace(key + "-stride", "Negative {} stride {}", what, stride);
|
||||
if (legal) return true;
|
||||
warnOnceTrace(key + "-" + slot, "Ignoring {} {} with illegal size {} / type 0x{}", what, slot, size, Integer.toHexString(type));
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isValidVertexAttribIndex(int index, String function) {
|
||||
if (index >= 0 && index < VAOManager.MAX_ATTRIBS) return true;
|
||||
warnOnceTrace(function, "{}({}) is outside the {} supported vertex attributes; ignoring", function, index, VAOManager.MAX_ATTRIBS);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void ffpClientArrayPointer(int conv, int size, int type, boolean normalized, int stride, long offset) {
|
||||
rejectExitCapture();
|
||||
if (!isLegalClientArray(conv, size, type, stride)) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.vaos.setConventional(conv, size, type, normalized, stride, offset, glCtx.boundVBO)) {
|
||||
RENDER_BACKEND.vertexAttribPointer(VAOManager.conventionalLocation(conv), size, type, normalized, stride, offset);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ffpClientArrayPointer(int conv, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||
rejectExitCapture();
|
||||
if (!isLegalClientArray(conv, size, type, stride)) return;
|
||||
ctx().vaos.setConventional(conv, size, type, normalized, stride, pointer);
|
||||
}
|
||||
|
||||
static final int FIELD_SIZE = 0, FIELD_TYPE = 1 << 8, FIELD_STRIDE = 2 << 8, FIELD_BINDING = 3 << 8, FIELD_POINTER = 4 << 8;
|
||||
|
||||
static int clientArrayField(GLContextState glCtx, int pname) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_VERTEX_ARRAY_SIZE -> VAOManager.CONV_POSITION | FIELD_SIZE;
|
||||
case GL11.GL_VERTEX_ARRAY_TYPE -> VAOManager.CONV_POSITION | FIELD_TYPE;
|
||||
case GL11.GL_VERTEX_ARRAY_STRIDE -> VAOManager.CONV_POSITION | FIELD_STRIDE;
|
||||
case GL15.GL_VERTEX_ARRAY_BUFFER_BINDING -> VAOManager.CONV_POSITION | FIELD_BINDING;
|
||||
case GL11.GL_VERTEX_ARRAY_POINTER -> VAOManager.CONV_POSITION | FIELD_POINTER;
|
||||
case GL11.GL_NORMAL_ARRAY_TYPE -> VAOManager.CONV_NORMAL | FIELD_TYPE;
|
||||
case GL11.GL_NORMAL_ARRAY_STRIDE -> VAOManager.CONV_NORMAL | FIELD_STRIDE;
|
||||
case GL15.GL_NORMAL_ARRAY_BUFFER_BINDING -> VAOManager.CONV_NORMAL | FIELD_BINDING;
|
||||
case GL11.GL_NORMAL_ARRAY_POINTER -> VAOManager.CONV_NORMAL | FIELD_POINTER;
|
||||
case GL11.GL_COLOR_ARRAY_SIZE -> VAOManager.CONV_COLOR | FIELD_SIZE;
|
||||
case GL11.GL_COLOR_ARRAY_TYPE -> VAOManager.CONV_COLOR | FIELD_TYPE;
|
||||
case GL11.GL_COLOR_ARRAY_STRIDE -> VAOManager.CONV_COLOR | FIELD_STRIDE;
|
||||
case GL15.GL_COLOR_ARRAY_BUFFER_BINDING -> VAOManager.CONV_COLOR | FIELD_BINDING;
|
||||
case GL11.GL_COLOR_ARRAY_POINTER -> VAOManager.CONV_COLOR | FIELD_POINTER;
|
||||
case GL11.GL_INDEX_ARRAY_TYPE -> VAOManager.CONV_INDEX | FIELD_TYPE;
|
||||
case GL11.GL_INDEX_ARRAY_STRIDE -> VAOManager.CONV_INDEX | FIELD_STRIDE;
|
||||
case GL15.GL_INDEX_ARRAY_BUFFER_BINDING -> VAOManager.CONV_INDEX | FIELD_BINDING;
|
||||
case GL11.GL_INDEX_ARRAY_POINTER -> VAOManager.CONV_INDEX | FIELD_POINTER;
|
||||
case GL11.GL_EDGE_FLAG_ARRAY_STRIDE -> VAOManager.CONV_EDGE_FLAG | FIELD_STRIDE;
|
||||
case GL15.GL_EDGE_FLAG_ARRAY_BUFFER_BINDING -> VAOManager.CONV_EDGE_FLAG | FIELD_BINDING;
|
||||
case GL11.GL_EDGE_FLAG_ARRAY_POINTER -> VAOManager.CONV_EDGE_FLAG | FIELD_POINTER;
|
||||
case GL14.GL_SECONDARY_COLOR_ARRAY_SIZE -> VAOManager.CONV_SECONDARY_COLOR | FIELD_SIZE;
|
||||
case GL14.GL_SECONDARY_COLOR_ARRAY_TYPE -> VAOManager.CONV_SECONDARY_COLOR | FIELD_TYPE;
|
||||
case GL14.GL_SECONDARY_COLOR_ARRAY_STRIDE -> VAOManager.CONV_SECONDARY_COLOR | FIELD_STRIDE;
|
||||
case GL15.GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING -> VAOManager.CONV_SECONDARY_COLOR | FIELD_BINDING;
|
||||
case GL14.GL_SECONDARY_COLOR_ARRAY_POINTER -> VAOManager.CONV_SECONDARY_COLOR | FIELD_POINTER;
|
||||
case GL14.GL_FOG_COORDINATE_ARRAY_TYPE -> VAOManager.CONV_FOG_COORD | FIELD_TYPE;
|
||||
case GL14.GL_FOG_COORDINATE_ARRAY_STRIDE -> VAOManager.CONV_FOG_COORD | FIELD_STRIDE;
|
||||
case GL15.GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING -> VAOManager.CONV_FOG_COORD | FIELD_BINDING;
|
||||
case GL14.GL_FOG_COORDINATE_ARRAY_POINTER -> VAOManager.CONV_FOG_COORD | FIELD_POINTER;
|
||||
case GL11.GL_TEXTURE_COORD_ARRAY_SIZE -> texCoordConventional(glCtx) | FIELD_SIZE;
|
||||
case GL11.GL_TEXTURE_COORD_ARRAY_TYPE -> texCoordConventional(glCtx) | FIELD_TYPE;
|
||||
case GL11.GL_TEXTURE_COORD_ARRAY_STRIDE -> texCoordConventional(glCtx) | FIELD_STRIDE;
|
||||
case GL15.GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING -> texCoordConventional(glCtx) | FIELD_BINDING;
|
||||
case GL11.GL_TEXTURE_COORD_ARRAY_POINTER -> texCoordConventional(glCtx) | FIELD_POINTER;
|
||||
default -> -1;
|
||||
};
|
||||
}
|
||||
|
||||
static int clientArrayParam(GLContextState glCtx, int key) {
|
||||
final int conv = key & 0xFF;
|
||||
final VAOManager.Attrib a = glCtx.vaos.conventional(conv);
|
||||
final boolean specified = a != null && a.size != 0;
|
||||
return switch (key & ~0xFF) {
|
||||
case FIELD_SIZE -> specified ? a.size : conv == VAOManager.CONV_SECONDARY_COLOR ? 3 : 4;
|
||||
case FIELD_TYPE -> specified ? a.type : GL11.GL_FLOAT;
|
||||
case FIELD_STRIDE -> specified ? a.stride : 0;
|
||||
default -> specified ? a.vboId : 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static ByteBuffer glGetPointer(int pname, long result_size) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final int key = clientArrayField(glCtx, pname);
|
||||
if ((key & ~0xFF) != FIELD_POINTER) return null;
|
||||
final VAOManager.Attrib a = glCtx.vaos.conventional(key & 0xFF);
|
||||
if (a == null) return null;
|
||||
final long address = a.clientPointer != null ? MemoryUtilities.memAddress(a.clientPointer) : a.offset;
|
||||
return address == 0 ? null : MemoryUtilities.memByteBuffer(address, (int) result_size);
|
||||
}
|
||||
|
||||
public static void glEdgeFlagPointer(int stride, ByteBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_EDGE_FLAG, 1, GL11.GL_UNSIGNED_BYTE, false, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glEdgeFlagPointer(int stride, long pointer_buffer_offset) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_EDGE_FLAG, 1, GL11.GL_UNSIGNED_BYTE, false, stride, pointer_buffer_offset);
|
||||
}
|
||||
|
||||
public static void glFogCoordPointer(int stride, FloatBuffer data) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_FOG_COORD, 1, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(data));
|
||||
}
|
||||
|
||||
public static void glFogCoordPointer(int stride, DoubleBuffer data) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_FOG_COORD, 1, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(data));
|
||||
}
|
||||
|
||||
public static void glFogCoordPointer(int type, int stride, long data_buffer_offset) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_FOG_COORD, 1, type, false, stride, data_buffer_offset);
|
||||
}
|
||||
|
||||
public static void glSecondaryColorPointer(int size, int stride, FloatBuffer data) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_SECONDARY_COLOR, size, GL11.GL_FLOAT, true, stride, MemoryUtilities.memByteBuffer(data));
|
||||
}
|
||||
|
||||
public static void glSecondaryColorPointer(int size, int stride, DoubleBuffer data) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_SECONDARY_COLOR, size, GL11.GL_DOUBLE, true, stride, MemoryUtilities.memByteBuffer(data));
|
||||
}
|
||||
|
||||
public static void glSecondaryColorPointer(int size, boolean unsigned, int stride, ByteBuffer data) {
|
||||
final int type = unsigned ? GL11.GL_UNSIGNED_BYTE : GL11.GL_BYTE;
|
||||
ffpClientArrayPointer(VAOManager.CONV_SECONDARY_COLOR, size, type, true, stride, data);
|
||||
}
|
||||
|
||||
public static void glSecondaryColorPointer(int size, int type, int stride, long data_buffer_offset) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_SECONDARY_COLOR, size, type, true, stride, data_buffer_offset);
|
||||
}
|
||||
|
||||
static void pointAttrib(GLContextState glCtx, int index) {
|
||||
final VAOManager vaos = glCtx.vaos;
|
||||
final VAOManager.Attrib a = vaos.attrib(index);
|
||||
if (a == null) return;
|
||||
RENDER_BACKEND.vertexAttribDivisor(index, a.divisor);
|
||||
if (a.size == 0 || a.vboId == 0 || !vaos.isBufferLive(a)) return;
|
||||
if (glCtx.boundVBO != a.vboId) GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, a.vboId);
|
||||
if (a.integer) {
|
||||
RENDER_BACKEND.vertexAttribIPointer(index, a.size, a.type, a.stride, a.offset);
|
||||
} else {
|
||||
RENDER_BACKEND.vertexAttribPointer(index, a.size, a.type, a.normalized, a.stride, a.offset);
|
||||
}
|
||||
}
|
||||
|
||||
private static void repointAttrib(GLContextState glCtx, int index) {
|
||||
final int savedVBO = glCtx.boundVBO;
|
||||
pointAttrib(glCtx, index);
|
||||
if (glCtx.boundVBO != savedVBO) GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int stride, IntBuffer pointer) {
|
||||
glVertexPointer(size, GL11.GL_INT, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int stride, ShortBuffer pointer) {
|
||||
glVertexPointer(size, GL11.GL_SHORT, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int stride, FloatBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_POSITION, size, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int stride, DoubleBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_POSITION, size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int type, int stride, ByteBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_POSITION, size, type, false, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_POSITION, size, type, false, stride, pointer_buffer_offset);
|
||||
}
|
||||
|
||||
public static void glColorPointer(int size, int stride, FloatBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_COLOR, size, GL11.GL_FLOAT, Usage.COLOR.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glColorPointer(int size, int stride, DoubleBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_COLOR, size, GL11.GL_DOUBLE, Usage.COLOR.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glColorPointer(int size, int type, int stride, ByteBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_COLOR, size, type, Usage.COLOR.isNormalized(), stride, pointer);
|
||||
}
|
||||
|
||||
public static void glColorPointer(int size, boolean unsigned, int stride, ByteBuffer pointer) {
|
||||
final int type = unsigned ? GL11.GL_UNSIGNED_BYTE : GL11.GL_BYTE;
|
||||
ffpClientArrayPointer(VAOManager.CONV_COLOR, size, type, Usage.COLOR.isNormalized(), stride, pointer);
|
||||
}
|
||||
|
||||
public static void glColorPointer(int size, int type, int stride, long pointer_buffer_offset) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_COLOR, size, type, Usage.COLOR.isNormalized(), stride, pointer_buffer_offset);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int stride, FloatBuffer pointer) {
|
||||
glNormalPointer(GL11.GL_FLOAT, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int stride, ByteBuffer pointer) {
|
||||
glNormalPointer(GL11.GL_BYTE, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int stride, IntBuffer pointer) {
|
||||
glNormalPointer(GL11.GL_INT, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int stride, DoubleBuffer pointer) {
|
||||
glNormalPointer(GL11.GL_DOUBLE, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, ByteBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_NORMAL, 3, type, Usage.NORMAL.isNormalized(), stride, pointer);
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, FloatBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_NORMAL, 3, GL11.GL_FLOAT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, ShortBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_NORMAL, 3, GL11.GL_SHORT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, IntBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_NORMAL, 3, GL11.GL_INT, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, DoubleBuffer pointer) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_NORMAL, 3, GL11.GL_DOUBLE, Usage.NORMAL.isNormalized(), stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glNormalPointer(int type, int stride, long pointer_buffer_offset) {
|
||||
ffpClientArrayPointer(VAOManager.CONV_NORMAL, 3, type, Usage.NORMAL.isNormalized(), stride, pointer_buffer_offset);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, ByteBuffer pointer) {
|
||||
ffpClientArrayPointer(texCoordConventional(ctx()), size, type, false, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int stride, FloatBuffer pointer) {
|
||||
glTexCoordPointer(size, GL11.GL_FLOAT, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int stride, IntBuffer pointer) {
|
||||
glTexCoordPointer(size, GL11.GL_INT, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int stride, ShortBuffer pointer) {
|
||||
glTexCoordPointer(size, GL11.GL_SHORT, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int stride, DoubleBuffer pointer) {
|
||||
glTexCoordPointer(size, GL11.GL_DOUBLE, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, FloatBuffer pointer) {
|
||||
ffpClientArrayPointer(texCoordConventional(ctx()), size, GL11.GL_FLOAT, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, ShortBuffer pointer) {
|
||||
ffpClientArrayPointer(texCoordConventional(ctx()), size, GL11.GL_SHORT, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, IntBuffer pointer) {
|
||||
ffpClientArrayPointer(texCoordConventional(ctx()), size, GL11.GL_INT, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, DoubleBuffer pointer) {
|
||||
ffpClientArrayPointer(texCoordConventional(ctx()), size, GL11.GL_DOUBLE, false, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) {
|
||||
ffpClientArrayPointer(texCoordConventional(ctx()), size, type, false, stride, pointer_buffer_offset);
|
||||
}
|
||||
|
||||
public static void glEnableClientState(int cap) {
|
||||
rejectExitCapture();
|
||||
setClientArrayCap(ctx(), cap, true);
|
||||
}
|
||||
|
||||
public static void glDisableClientState(int cap) {
|
||||
rejectExitCapture();
|
||||
setClientArrayCap(ctx(), cap, false);
|
||||
}
|
||||
|
||||
static boolean setClientArrayCap(GLContextState glCtx, int cap, boolean enabled) {
|
||||
final int conv = clientStateToConventional(glCtx, cap);
|
||||
if (conv < 0) return false;
|
||||
setClientArrayEnabled(glCtx, conv, enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void setClientArrayEnabled(GLContextState glCtx, int conv, boolean enabled) {
|
||||
final VAOManager vaos = glCtx.vaos;
|
||||
final boolean repoint = vaos.setConventionalEnabled(conv, enabled);
|
||||
final int index = VAOManager.conventionalLocation(conv);
|
||||
if (index >= 0) {
|
||||
if (repoint) repointAttrib(glCtx, index);
|
||||
syncAttribEnable(glCtx, index);
|
||||
}
|
||||
final int flag = conventionalVertexFlag(conv);
|
||||
if (flag == 0) return;
|
||||
if (enabled) {
|
||||
vaos.enableClientVertexFlag(flag);
|
||||
} else {
|
||||
vaos.disableClientVertexFlag(flag);
|
||||
}
|
||||
}
|
||||
|
||||
static void syncAttribEnable(GLContextState glCtx, int index) {
|
||||
if (glCtx.vaos.isAttribEnabled(index)) {
|
||||
RENDER_BACKEND.enableVertexAttribArray(index);
|
||||
} else {
|
||||
RENDER_BACKEND.disableVertexAttribArray(index);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, long offset) {
|
||||
rejectExitCapture();
|
||||
if (!isLegalVertexAttrib(index, size, type, stride, false)) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.vaos.setAttribute(index, size, type, normalized, stride, offset, glCtx.boundVBO)) {
|
||||
RENDER_BACKEND.vertexAttribPointer(index, size, type, normalized, stride, offset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, boolean normalized, int stride, FloatBuffer pointer) {
|
||||
glVertexAttribPointer(index, size, GL11.GL_FLOAT, normalized, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, FloatBuffer pointer) {
|
||||
glVertexAttribPointer(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, DoubleBuffer pointer) {
|
||||
glVertexAttribPointer(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, IntBuffer pointer) {
|
||||
glVertexAttribPointer(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ShortBuffer pointer) {
|
||||
glVertexAttribPointer(index, size, type, normalized, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||
rejectExitCapture();
|
||||
if (!isLegalVertexAttrib(index, size, type, stride, false)) return;
|
||||
ctx().vaos.setAttribute(index, size, type, normalized, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, long offset) {
|
||||
rejectExitCapture();
|
||||
if (!isLegalVertexAttrib(index, size, type, stride, true)) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.vaos.setIntegerAttribute(index, size, type, stride, offset, glCtx.boundVBO)) {
|
||||
RENDER_BACKEND.vertexAttribIPointer(index, size, type, stride, offset);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ByteBuffer pointer) {
|
||||
rejectExitCapture();
|
||||
if (!isLegalVertexAttrib(index, size, type, stride, true)) return;
|
||||
ctx().vaos.setIntegerAttribute(index, size, type, stride, pointer);
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, IntBuffer pointer) {
|
||||
glVertexAttribIPointer(index, size, type, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexAttribIPointer(int index, int size, int type, int stride, ShortBuffer pointer) {
|
||||
glVertexAttribIPointer(index, size, type, stride, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glVertexAttribDivisor(int index, int divisor) {
|
||||
rejectExitCapture();
|
||||
if (ctx().vaos.setDivisor(index, divisor)) RENDER_BACKEND.vertexAttribDivisor(index, divisor);
|
||||
}
|
||||
|
||||
public static void glVertexAttribDivisorARB(int index, int divisor) { glVertexAttribDivisor(index, divisor); }
|
||||
public static void glBindVertexBuffer(int bindingindex, int buffer, long offset, int stride) { rejectExitCapture(); RENDER_BACKEND.bindVertexBuffer(bindingindex, buffer, offset, stride); }
|
||||
public static void glVertexAttribFormat(int attribindex, int size, int type, boolean normalized, int relativeoffset) { rejectExitCapture(); RENDER_BACKEND.vertexAttribFormat(attribindex, size, type, normalized, relativeoffset); }
|
||||
public static void glVertexAttribIFormat(int attribindex, int size, int type, int relativeoffset) { rejectExitCapture(); RENDER_BACKEND.vertexAttribIFormat(attribindex, size, type, relativeoffset); }
|
||||
public static void glVertexAttribBinding(int attribindex, int bindingindex) { rejectExitCapture(); RENDER_BACKEND.vertexAttribBinding(attribindex, bindingindex); }
|
||||
|
||||
public static void glEnableVertexAttribArray(int index) {
|
||||
rejectExitCapture();
|
||||
if (!isValidVertexAttribIndex(index, "glEnableVertexAttribArray")) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.vaos.enableAttribute(index)) repointAttrib(glCtx, index);
|
||||
RENDER_BACKEND.enableVertexAttribArray(index);
|
||||
}
|
||||
|
||||
public static void glDisableVertexAttribArray(int index) {
|
||||
rejectExitCapture();
|
||||
if (!isValidVertexAttribIndex(index, "glDisableVertexAttribArray")) return;
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.vaos.disableAttribute(index)) repointAttrib(glCtx, index);
|
||||
if (!glCtx.vaos.isAttribEnabled(index)) RENDER_BACKEND.disableVertexAttribArray(index);
|
||||
}
|
||||
|
||||
static int clientStateToConventional(GLContextState glCtx, int cap) {
|
||||
return switch (cap) {
|
||||
case GL11.GL_VERTEX_ARRAY -> VAOManager.CONV_POSITION;
|
||||
case GL11.GL_NORMAL_ARRAY -> VAOManager.CONV_NORMAL;
|
||||
case GL11.GL_COLOR_ARRAY -> VAOManager.CONV_COLOR;
|
||||
case GL11.GL_INDEX_ARRAY -> VAOManager.CONV_INDEX;
|
||||
case GL11.GL_EDGE_FLAG_ARRAY -> VAOManager.CONV_EDGE_FLAG;
|
||||
case GL14.GL_SECONDARY_COLOR_ARRAY -> VAOManager.CONV_SECONDARY_COLOR;
|
||||
case GL14.GL_FOG_COORDINATE_ARRAY -> VAOManager.CONV_FOG_COORD;
|
||||
case GL11.GL_TEXTURE_COORD_ARRAY -> texCoordConventional(glCtx);
|
||||
default -> -1;
|
||||
};
|
||||
}
|
||||
|
||||
private static int conventionalVertexFlag(int conv) {
|
||||
return switch (conv) {
|
||||
case VAOManager.CONV_COLOR -> VertexFlags.COLOR_BIT;
|
||||
case VAOManager.CONV_NORMAL -> VertexFlags.NORMAL_BIT;
|
||||
case VAOManager.CONV_TEX0 -> VertexFlags.TEXTURE_BIT;
|
||||
case VAOManager.CONV_TEX0 + 1 -> VertexFlags.BRIGHTNESS_BIT;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static void glInterleavedArrays(int format, int stride, long pointer) {
|
||||
interleavedArrays(format, stride, pointer, null);
|
||||
}
|
||||
|
||||
private static void interleavedPointer(int conv, int size, int type, boolean normalized, int stride, long pointer, ByteBuffer base, int offset) {
|
||||
if (base == null) {
|
||||
ffpClientArrayPointer(conv, size, type, normalized, stride, pointer + offset);
|
||||
} else {
|
||||
ffpClientArrayPointer(conv, size, type, normalized, stride, MemoryUtilities.memSlice(base, offset, base.remaining() - offset));
|
||||
}
|
||||
}
|
||||
|
||||
private static void interleavedArrays(int format, int stride, long pointer, ByteBuffer base) {
|
||||
rejectExitCapture();
|
||||
// Mesa _mesa_get_interleaved_layout decomposition
|
||||
final int f = 4; // sizeof(float)
|
||||
final int c = f * ((4 + (f - 1)) / f); // 4 ubytes padded to float alignment = 4
|
||||
|
||||
boolean tflag = false, cflag = false, nflag = false;
|
||||
int tcomps = 0, ccomps = 0, vcomps = 0;
|
||||
int ctype = 0;
|
||||
final int toffset = 0;
|
||||
int coffset = 0;
|
||||
int noffset = 0;
|
||||
int voffset = 0;
|
||||
final int defstride;
|
||||
|
||||
switch (format) {
|
||||
case GL11.GL_V2F:
|
||||
vcomps = 2; defstride = 2 * f; break;
|
||||
case GL11.GL_V3F:
|
||||
vcomps = 3; defstride = 3 * f; break;
|
||||
case GL11.GL_C4UB_V2F:
|
||||
cflag = true; ccomps = 4; vcomps = 2;
|
||||
ctype = GL11.GL_UNSIGNED_BYTE; voffset = c; defstride = c + 2 * f; break;
|
||||
case GL11.GL_C4UB_V3F:
|
||||
cflag = true; ccomps = 4; vcomps = 3;
|
||||
ctype = GL11.GL_UNSIGNED_BYTE; voffset = c; defstride = c + 3 * f; break;
|
||||
case GL11.GL_C3F_V3F:
|
||||
cflag = true; ccomps = 3; vcomps = 3;
|
||||
ctype = GL11.GL_FLOAT; voffset = 3 * f; defstride = 6 * f; break;
|
||||
case GL11.GL_N3F_V3F:
|
||||
nflag = true; vcomps = 3;
|
||||
voffset = 3 * f; defstride = 6 * f; break;
|
||||
case GL11.GL_C4F_N3F_V3F:
|
||||
cflag = true; nflag = true; ccomps = 4; vcomps = 3;
|
||||
ctype = GL11.GL_FLOAT; noffset = 4 * f; voffset = 7 * f; defstride = 10 * f; break;
|
||||
case GL11.GL_T2F_V3F:
|
||||
tflag = true; tcomps = 2; vcomps = 3;
|
||||
voffset = 2 * f; defstride = 5 * f; break;
|
||||
case GL11.GL_T4F_V4F:
|
||||
tflag = true; tcomps = 4; vcomps = 4;
|
||||
voffset = 4 * f; defstride = 8 * f; break;
|
||||
case GL11.GL_T2F_C4UB_V3F:
|
||||
tflag = true; cflag = true; tcomps = 2; ccomps = 4; vcomps = 3;
|
||||
ctype = GL11.GL_UNSIGNED_BYTE; coffset = 2 * f; voffset = c + 2 * f; defstride = c + 5 * f; break;
|
||||
case GL11.GL_T2F_C3F_V3F:
|
||||
tflag = true; cflag = true; tcomps = 2; ccomps = 3; vcomps = 3;
|
||||
ctype = GL11.GL_FLOAT; coffset = 2 * f; voffset = 5 * f; defstride = 8 * f; break;
|
||||
case GL11.GL_T2F_N3F_V3F:
|
||||
tflag = true; nflag = true; tcomps = 2; vcomps = 3;
|
||||
noffset = 2 * f; voffset = 5 * f; defstride = 8 * f; break;
|
||||
case GL11.GL_T2F_C4F_N3F_V3F:
|
||||
tflag = true; cflag = true; nflag = true; tcomps = 2; ccomps = 4; vcomps = 3;
|
||||
ctype = GL11.GL_FLOAT; coffset = 2 * f; noffset = 6 * f; voffset = 9 * f; defstride = 12 * f; break;
|
||||
case GL11.GL_T4F_C4F_N3F_V4F:
|
||||
tflag = true; cflag = true; nflag = true; tcomps = 4; ccomps = 4; vcomps = 4;
|
||||
ctype = GL11.GL_FLOAT; coffset = 4 * f; noffset = 8 * f; voffset = 11 * f; defstride = 15 * f; break;
|
||||
default:
|
||||
return; // Invalid format
|
||||
}
|
||||
|
||||
if (stride == 0) stride = defstride;
|
||||
|
||||
if (tflag) {
|
||||
glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
|
||||
interleavedPointer(texCoordConventional(ctx()), tcomps, GL11.GL_FLOAT, false, stride, pointer, base, toffset);
|
||||
} else {
|
||||
glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
if (cflag) {
|
||||
glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
interleavedPointer(VAOManager.CONV_COLOR, ccomps, ctype, Usage.COLOR.isNormalized(), stride, pointer, base, coffset);
|
||||
} else {
|
||||
glDisableClientState(GL11.GL_COLOR_ARRAY);
|
||||
}
|
||||
|
||||
if (nflag) {
|
||||
glEnableClientState(GL11.GL_NORMAL_ARRAY);
|
||||
interleavedPointer(VAOManager.CONV_NORMAL, 3, GL11.GL_FLOAT, Usage.NORMAL.isNormalized(), stride, pointer, base, noffset);
|
||||
} else {
|
||||
glDisableClientState(GL11.GL_NORMAL_ARRAY);
|
||||
}
|
||||
|
||||
glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
interleavedPointer(VAOManager.CONV_POSITION, vcomps, GL11.GL_FLOAT, false, stride, pointer, base, voffset);
|
||||
}
|
||||
|
||||
public static void glInterleavedArrays(int format, int stride, ByteBuffer pointer) {
|
||||
interleavedArrays(format, stride, 0L, pointer);
|
||||
}
|
||||
|
||||
public static void glInterleavedArrays(int format, int stride, FloatBuffer pointer) {
|
||||
interleavedArrays(format, stride, 0L, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glInterleavedArrays(int format, int stride, DoubleBuffer pointer) {
|
||||
interleavedArrays(format, stride, 0L, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glInterleavedArrays(int format, int stride, IntBuffer pointer) {
|
||||
interleavedArrays(format, stride, 0L, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glInterleavedArrays(int format, int stride, ShortBuffer pointer) {
|
||||
interleavedArrays(format, stride, 0L, MemoryUtilities.memByteBuffer(pointer));
|
||||
}
|
||||
|
||||
public static void glBindVertexArray(int array) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
if (DisplayListManager.isRecording()) {
|
||||
DisplayListManager.recordBindVAO(array);
|
||||
// Since the vao needs to be bound to do stuff like state setup & data upload, it'll still execute the bind call.
|
||||
// This is technically wrong, but I'm not sure if there's a better solution here.
|
||||
}
|
||||
bindVertexArrayInternal(glCtx, array == 0 ? glCtx.defaultVAO : array);
|
||||
}
|
||||
|
||||
static void bindVertexArrayInternal(GLContextState glCtx, int array) {
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
if (glCtx.boundVAO != array) {
|
||||
glCtx.boundVAO = array;
|
||||
glCtx.vaos.onBindVertexArrayPre(array);
|
||||
RENDER_BACKEND.bindVertexArray(array);
|
||||
}
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void glDeleteVertexArrays(int array) {
|
||||
rejectExitCapture();
|
||||
final GLContextState glCtx = ctx();
|
||||
final boolean locked = acquireDrawLock();
|
||||
try {
|
||||
glCtx.vaos.onDeleteVertexArray(array);
|
||||
if (array == glCtx.boundVAO) {
|
||||
// Deleting the bound VAO implicitly unbinds it. Rebind the default VAO.
|
||||
bindVertexArrayInternal(glCtx, glCtx.defaultVAO);
|
||||
}
|
||||
RENDER_BACKEND.deleteVertexArrays(array);
|
||||
} finally {
|
||||
if (locked) releaseDrawLock();
|
||||
}
|
||||
}
|
||||
|
||||
public static int glGenVertexArrays() {
|
||||
requireContext("glGenVertexArrays");
|
||||
return RENDER_BACKEND.genVertexArrays();
|
||||
}
|
||||
|
||||
public static boolean glIsVertexArray(int array) {
|
||||
rejectExitCapture();
|
||||
return RENDER_BACKEND.isVertexArray(array);
|
||||
}
|
||||
|
||||
public static void glBindVertexArrayAPPLE(int array) {
|
||||
glBindVertexArray(array);
|
||||
}
|
||||
|
||||
public static int getBoundVAO() {
|
||||
return ctx().boundVAO;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.backend.ScreenCapture;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.BatchStateGuard;
|
||||
import com.gtnewhorizons.angelica.glsm.states.PixelStoreState;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL21;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public final class GLScreenCapture extends ScreenCapture {
|
||||
|
||||
private final int[] textures = new int[RING];
|
||||
private final int[] framebuffers = new int[RING];
|
||||
private final int[] buffers = new int[RING];
|
||||
|
||||
public GLScreenCapture(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean start(int slot, int srcFramebuffer, int srcWidth, int srcHeight) {
|
||||
final int width = width();
|
||||
final int height = height();
|
||||
final int previousRead = GLSMFramebuffer.getReadFramebuffer();
|
||||
final int previousDraw = GLSMFramebuffer.getDrawFramebuffer();
|
||||
final int previousPack = GLStateManager.ctx().boundPixelPackBuffer;
|
||||
final boolean scissor = GLSMRasterizer.getScissorTest().isEnabled();
|
||||
BatchStateGuard.suspend();
|
||||
try {
|
||||
if (framebuffers[slot] == 0) create(slot);
|
||||
if (scissor) GLSMEnable.glDisable(GL11.GL_SCISSOR_TEST);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, srcFramebuffer);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, framebuffers[slot]);
|
||||
GLSMFramebuffer.glBlitFramebuffer(0, 0, srcWidth, srcHeight, 0, 0, width, height, GL11.GL_COLOR_BUFFER_BIT, GL11.GL_LINEAR);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, framebuffers[slot]);
|
||||
GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, buffers[slot]);
|
||||
GLSMTextures.forcePixelPackState(PixelStoreState.DEFAULT);
|
||||
GLSMFramebuffer.glReadPixels(0, 0, width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, 0L);
|
||||
return true;
|
||||
} finally {
|
||||
GLSMTextures.restorePixelPackState(PixelStoreState.DEFAULT);
|
||||
GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, previousPack);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, previousRead);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, previousDraw);
|
||||
if (scissor) GLSMEnable.glEnable(GL11.GL_SCISSOR_TEST);
|
||||
BatchStateGuard.resume();
|
||||
}
|
||||
}
|
||||
|
||||
private void create(int slot) {
|
||||
final int previousTexture = GLSMTextures.getBoundTextureForServerState();
|
||||
final int texture;
|
||||
try {
|
||||
texture = GLSMTextures.glGenTextures();
|
||||
GLSMTextures.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
GLSMTextures.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width(), height(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||
} finally {
|
||||
GLSMTextures.glBindTexture(GL11.GL_TEXTURE_2D, previousTexture);
|
||||
}
|
||||
textures[slot] = texture;
|
||||
framebuffers[slot] = GLSMFramebuffer.glGenFramebuffers();
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, framebuffers[slot]);
|
||||
GLSMFramebuffer.glFramebufferTexture2D(GL30.GL_DRAW_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, texture, 0);
|
||||
buffers[slot] = GLSMBuffers.glGenBuffers();
|
||||
GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, buffers[slot]);
|
||||
GLSMBuffers.glBufferData(GL21.GL_PIXEL_PACK_BUFFER, (long) width() * height() * 4, GL15.GL_STREAM_READ);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long map(int slot) {
|
||||
final int previousPack = GLStateManager.ctx().boundPixelPackBuffer;
|
||||
GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, buffers[slot]);
|
||||
try {
|
||||
return GLSMBuffers.glMapBufferRangeAddress(GL21.GL_PIXEL_PACK_BUFFER, 0L, (long) width() * height() * 4, GL30.GL_MAP_READ_BIT);
|
||||
} finally {
|
||||
GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, previousPack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unmap(int slot) {
|
||||
final int previousPack = GLStateManager.ctx().boundPixelPackBuffer;
|
||||
GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, buffers[slot]);
|
||||
GLSMBuffers.glUnmapBuffer(GL21.GL_PIXEL_PACK_BUFFER);
|
||||
GLSMBuffers.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, previousPack);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deleteSlot(int slot) {
|
||||
if (buffers[slot] != 0) GLSMBuffers.glDeleteBuffers(buffers[slot]);
|
||||
if (framebuffers[slot] != 0) GLSMFramebuffer.glDeleteFramebuffers(framebuffers[slot]);
|
||||
if (textures[slot] != 0) GLSMTextures.glDeleteTextures(textures[slot]);
|
||||
buffers[slot] = 0;
|
||||
framebuffers[slot] = 0;
|
||||
textures[slot] = 0;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -25,10 +25,10 @@ public final class LTWWorkaround {
|
||||
oneTexel = BufferUtils.createByteBuffer(4);
|
||||
}
|
||||
oneTexel.clear();
|
||||
GLStateManager.forcePixelUnpackState(PixelStoreState.DEFAULT);
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLSMTextures.forcePixelUnpackState(PixelStoreState.DEFAULT);
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage2D(target, level, 0, 0, 1, 1, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, oneTexel);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLStateManager.restorePixelUnpackState(PixelStoreState.DEFAULT);
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
GLSMTextures.restorePixelUnpackState(PixelStoreState.DEFAULT);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ final class LegacyQueries {
|
||||
private static FloatBuffer fillScratch(GLContextState glCtx, int pname) {
|
||||
final FloatBuffer scratch = glCtx.queryScratch;
|
||||
scratch.clear();
|
||||
GLStateManager.glGetFloat(pname, scratch);
|
||||
GLSMQueries.glGetFloat(pname, scratch);
|
||||
return scratch;
|
||||
}
|
||||
|
||||
@@ -102,9 +102,9 @@ final class LegacyQueries {
|
||||
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));
|
||||
case BOOL -> GLSMQueries.glGetBoolean(glCtx, pname) ? GL11.GL_TRUE : GL11.GL_FALSE;
|
||||
case FLOAT -> lround(GLSMQueries.glGetFloat(glCtx, pname));
|
||||
case FLOATN -> floatToInt(GLSMQueries.glGetFloat(glCtx, pname));
|
||||
default -> throw uncached(pname);
|
||||
};
|
||||
}
|
||||
@@ -114,8 +114,8 @@ final class LegacyQueries {
|
||||
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);
|
||||
case BOOL -> GLSMQueries.glGetBoolean(glCtx, pname) ? 1.0f : 0.0f;
|
||||
case INT -> (float) GLSMQueries.glGetInteger(glCtx, pname);
|
||||
default -> throw uncached(pname);
|
||||
};
|
||||
}
|
||||
@@ -125,8 +125,8 @@ final class LegacyQueries {
|
||||
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;
|
||||
case INT -> GLSMQueries.glGetInteger(glCtx, pname) != 0;
|
||||
case FLOAT, FLOATN -> GLSMQueries.glGetFloat(glCtx, pname) != 0.0f;
|
||||
default -> throw uncached(pname);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public final class QuadConverter {
|
||||
uploadAndDraw(glCtx, dst, quadCount * 6, GL11.GL_UNSIGNED_INT, 4, primcount, instanced);
|
||||
return;
|
||||
}
|
||||
GLStateManager.preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
GLSMDraws.preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
final int prevEbo = glCtx.vaos.boundEBO;
|
||||
ensureCapacity(first / 4 + quadCount);
|
||||
RENDER_BACKEND.bindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, eboId);
|
||||
@@ -143,7 +143,7 @@ public final class QuadConverter {
|
||||
}
|
||||
|
||||
private static void uploadAndDraw(GLContextState glCtx, ByteBuffer dst, int triIndexCount, int indexType, int bytesPerIndex, int primcount, boolean instanced) {
|
||||
GLStateManager.preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
GLSMDraws.preDraw(glCtx, GL11.GL_TRIANGLES);
|
||||
final int needed = triIndexCount * bytesPerIndex;
|
||||
final int prevEbo = glCtx.vaos.boundEBO;
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ public class RenderSystem {
|
||||
private static boolean supportsMultiDrawIndirect;
|
||||
private static boolean supportsBufferStorage;
|
||||
private static boolean supportsClearTexture;
|
||||
private static boolean supportsStencilTexturing;
|
||||
private static boolean supportsTextureStorage;
|
||||
private static boolean supportsTesselation;
|
||||
private static boolean supportsSamplerObjects;
|
||||
private static boolean supportsProgramBinary;
|
||||
@@ -61,7 +63,7 @@ public class RenderSystem {
|
||||
private static volatile boolean isGLES;
|
||||
private static volatile int glesVersion;
|
||||
private static volatile boolean glesDetected;
|
||||
private static volatile boolean hasClipCullDistance;
|
||||
private static boolean clipDistanceEmulated;
|
||||
|
||||
private static volatile boolean isLTW;
|
||||
private static volatile boolean ltwDetected;
|
||||
@@ -128,7 +130,14 @@ public class RenderSystem {
|
||||
supportsMultiDrawIndirect = GLStateManager.capabilities.OpenGL43 || GLStateManager.capabilities.GL_ARB_multi_draw_indirect;
|
||||
supportsBufferStorage = !isGLES && (GLStateManager.capabilities.OpenGL44 || GLStateManager.capabilities.GL_ARB_buffer_storage);
|
||||
supportsClearTexture = GLStateManager.capabilities.OpenGL44 || GLStateManager.capabilities.GL_ARB_clear_texture;
|
||||
hasClipCullDistance = !isGLES || hasExtension("GL_EXT_clip_cull_distance");
|
||||
supportsStencilTexturing = GLStateManager.capabilities.OpenGL43 || GLStateManager.capabilities.GL_ARB_stencil_texturing;
|
||||
supportsTextureStorage = isGLES ? glesVersion >= 300 : GLStateManager.capabilities.OpenGL42 || GLStateManager.capabilities.GL_ARB_texture_storage;
|
||||
final boolean esClipExt = !isGLES || hasExtension("GL_EXT_clip_cull_distance");
|
||||
final int maxClipDistances = esClipExt ? RENDER_BACKEND.getInteger(GL30.GL_MAX_CLIP_DISTANCES) : 0;
|
||||
clipDistanceEmulated = SystemProperties.EMULATE_CLIP_DISTANCES || maxClipDistances < GLStateManager.MAX_CLIP_PLANES;
|
||||
if (clipDistanceEmulated) {
|
||||
GLStateManager.LOGGER.info("Clip distances emulated (GL_MAX_CLIP_DISTANCES={}, forced={})", maxClipDistances, SystemProperties.EMULATE_CLIP_DISTANCES);
|
||||
}
|
||||
|
||||
// Cache maximum image units
|
||||
if (supportsImageLoadStore) {
|
||||
@@ -154,8 +163,8 @@ public class RenderSystem {
|
||||
maxSSBOBindings = 0;
|
||||
}
|
||||
|
||||
// Check for sampler objects support (GL 3.3+ or ARB extension)
|
||||
supportsSamplerObjects = GLStateManager.capabilities.OpenGL33 || GLStateManager.capabilities.GL_ARB_sampler_objects;
|
||||
supportsSamplerObjects = isGLES ? glesVersion >= 300
|
||||
: GLStateManager.capabilities.OpenGL33 || GLStateManager.capabilities.GL_ARB_sampler_objects;
|
||||
if (supportsSamplerObjects) {
|
||||
maxCombinedTextureImageUnits = RENDER_BACKEND.getInteger(GL20.GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
|
||||
}
|
||||
@@ -194,193 +203,231 @@ public class RenderSystem {
|
||||
}
|
||||
|
||||
public static void generateMipmaps(int texture, int mipmapTarget) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.generateMipmaps(texture, mipmapTarget);
|
||||
}
|
||||
|
||||
public static void bindAttributeLocation(int program, int index, CharSequence name) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.bindAttribLocation(program, index, name);
|
||||
}
|
||||
|
||||
public static void texImage2D(int texture, int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable ByteBuffer pixels) {
|
||||
final GLStateManager.GLESTexImageRemap remap = GLStateManager.remapTexImageForGLES(internalformat, format, type);
|
||||
GLStateManager.rejectExitCapture();
|
||||
final GLSMTextures.GLESTexImageRemap remap = GLSMTextures.remapTexImageForGLES(internalformat, format, type);
|
||||
internalformat = remap.internalFormat();
|
||||
format = remap.format();
|
||||
type = remap.type();
|
||||
GLStateManager.glBindTexture(target, texture);
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLSMTextures.glBindTexture(target, texture);
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
if (target == GL11.GL_TEXTURE_2D && level == 0) {
|
||||
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
public static void uniformMatrix4fv(int location, boolean transpose, FloatBuffer matrix) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniformMatrix4(location, transpose, matrix);
|
||||
}
|
||||
|
||||
public static void copyTexImage2D(int target, int level, int internalFormat, int x, int y, int width, int height, int border) {
|
||||
GLStateManager.glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
|
||||
GLSMTextures.glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
|
||||
}
|
||||
|
||||
public static void uniform1f(int location, float v0) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform1f(location, v0);
|
||||
}
|
||||
|
||||
public static void uniform1i(int location, int v0) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform1i(location, v0);
|
||||
}
|
||||
|
||||
public static void uniform2f(int location, float v0, float v1) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform2f(location, v0, v1);
|
||||
}
|
||||
|
||||
public static void uniform2i(int location, int v0, int v1) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform2i(location, v0, v1);
|
||||
}
|
||||
|
||||
public static void uniform3f(int location, float v0, float v1, float v2) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform3f(location, v0, v1, v2);
|
||||
}
|
||||
|
||||
public static void uniform3i(int location, int v0, int v1, int v2) {RENDER_BACKEND.uniform3i(location, v0, v1, v2);}
|
||||
public static void uniform3i(int location, int v0, int v1, int v2) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform3i(location, v0, v1, v2);
|
||||
}
|
||||
|
||||
public static void uniform4f(int location, float v0, float v1, float v2, float v3) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform4f(location, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
public static void uniform4i(int location, int v0, int v1, int v2, int v3) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.uniform4i(location, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
public static int getAttribLocation(int programId, String name) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return RENDER_BACKEND.getAttribLocation(programId, name);
|
||||
}
|
||||
|
||||
public static int getUniformLocation(int programId, String name) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return RENDER_BACKEND.getUniformLocation(programId, name);
|
||||
}
|
||||
|
||||
public static void texParameteriv(int texture, int target, int pname, IntBuffer params) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.texParameteriv(texture, target, pname, params);
|
||||
}
|
||||
|
||||
public static void copyTexSubImage2D(int destTexture, int target, int i, int i1, int i2, int i3, int i4, int width, int height) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.copyTexSubImage2D(destTexture, target, i, i1, i2, i3, i4, width, height);
|
||||
if (i == 0) TextureInfoCache.INSTANCE.onContentsChanged(destTexture);
|
||||
}
|
||||
|
||||
public static void texParameteri(int texture, int target, int pname, int param) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.texParameteri(texture, target, pname, param);
|
||||
}
|
||||
|
||||
public static void texParameterf(int texture, int target, int pname, float param) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.texParameterf(texture, target, pname, param);
|
||||
}
|
||||
|
||||
public static void textureImage2D(int texture, int target, int level, int internalformat, int width, int height, int border, int format, int type, ByteBuffer pixels) {
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLStateManager.rejectExitCapture();
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
dsaState.textureImage2D(texture, target, level, internalformat, width, height, border, format, type, pixels);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
TextureInfoCache.INSTANCE.onTextureImage2D(texture, target, level, internalformat, width, height);
|
||||
}
|
||||
|
||||
public static void textureImage2D(int texture, int target, int level, int internalformat, int width, int height, int border, int format, int type, IntBuffer pixels) {
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLStateManager.rejectExitCapture();
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
dsaState.textureImage2D(texture, target, level, internalformat, width, height, border, format, type, pixels);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
TextureInfoCache.INSTANCE.onTextureImage2D(texture, target, level, internalformat, width, height);
|
||||
}
|
||||
|
||||
public static void textureSubImage2D(int texture, int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer pixels) {
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLStateManager.rejectExitCapture();
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
dsaState.textureSubImage2D(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
if (level == 0) TextureInfoCache.INSTANCE.onContentsChanged(texture);
|
||||
}
|
||||
|
||||
public static void textureSubImage2D(int texture, int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer pixels) {
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLStateManager.rejectExitCapture();
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
dsaState.textureSubImage2D(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
if (level == 0) TextureInfoCache.INSTANCE.onContentsChanged(texture);
|
||||
}
|
||||
|
||||
public static void texImage1D(int texture, int target, int level, int internalformat, int width, int border, int format, int type, ByteBuffer pixels) {
|
||||
RENDER_BACKEND.bindTexture(target, texture);
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLStateManager.rejectExitCapture();
|
||||
GLSMTextures.glBindTexture(target, texture);
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage1D(target, level, internalformat, width, border, format, type, pixels);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static void texImage3D(int texture, int target, int level, int internalformat, int width, int height, int depth, int border, int format, int type, ByteBuffer pixels) {
|
||||
RENDER_BACKEND.bindTexture(target, texture);
|
||||
GLStateManager.suspendPixelUnpackBuffer();
|
||||
GLStateManager.rejectExitCapture();
|
||||
GLSMTextures.glBindTexture(target, texture);
|
||||
GLSMBuffers.suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
|
||||
GLStateManager.restorePixelUnpackBuffer();
|
||||
GLSMBuffers.restorePixelUnpackBuffer();
|
||||
}
|
||||
|
||||
public static String getProgramInfoLog(int program) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return RENDER_BACKEND.getProgramInfoLog(program, RENDER_BACKEND.getProgrami(program, GL20.GL_INFO_LOG_LENGTH));
|
||||
}
|
||||
|
||||
public static String getShaderInfoLog(int shader) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return RENDER_BACKEND.getShaderInfoLog(shader, RENDER_BACKEND.getShaderi(shader, GL20.GL_INFO_LOG_LENGTH));
|
||||
}
|
||||
|
||||
public static void drawBuffers(int framebuffer, IntBuffer buffers) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.drawBuffers(framebuffer, buffers);
|
||||
}
|
||||
|
||||
public static void readBuffer(int framebuffer, int buffer) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.readBuffer(framebuffer, buffer);
|
||||
}
|
||||
|
||||
public static String getActiveUniform(int program, int index, int maxLength, IntBuffer sizeType) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return RENDER_BACKEND.getActiveUniform(program, index, maxLength, sizeType);
|
||||
}
|
||||
|
||||
public static void readPixels(int x, int y, int width, int height, int format, int type, FloatBuffer pixels) {
|
||||
GLStateManager.suspendPixelPackBuffer();
|
||||
GLStateManager.rejectExitCapture();
|
||||
GLSMBuffers.suspendPixelPackBuffer();
|
||||
RENDER_BACKEND.readPixels(x, y, width, height, format, type, pixels);
|
||||
GLStateManager.restorePixelPackBuffer();
|
||||
GLSMBuffers.restorePixelPackBuffer();
|
||||
}
|
||||
|
||||
public static void bufferData(int target, FloatBuffer data, int usage) {
|
||||
GLStateManager.glBufferData(target, data, usage);
|
||||
GLSMBuffers.glBufferData(target, data, usage);
|
||||
}
|
||||
|
||||
public static int bufferStorage(int target, FloatBuffer data, int usage) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return dsaState.bufferStorage(target, data, usage);
|
||||
}
|
||||
|
||||
public static void vertexAttrib4f(int index, float v0, float v1, float v2, float v3) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.vertexAttrib4f(index, v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
public static void detachShader(int program, int shader) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.detachShader(program, shader);
|
||||
}
|
||||
|
||||
public static void framebufferTexture2D(int fb, int fbtarget, int attachment, int target, int texture, int levels) {
|
||||
TextureInfoCache.INSTANCE.onWrittenOutsideUploads(texture);
|
||||
GLStateManager.rejectExitCapture();
|
||||
dsaState.framebufferTexture2D(fb, fbtarget, attachment, target, texture, levels);
|
||||
}
|
||||
|
||||
public static int getTexParameteri(int texture, int target, int pname) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return dsaState.getTexParameteri(texture, target, pname);
|
||||
}
|
||||
|
||||
public static float getTexParameterf(int texture, int target, int pname) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return dsaState.getTexParameterf(texture, target, pname);
|
||||
}
|
||||
|
||||
public static int getTexLevelParameteri(int texture, int level, int pname) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return dsaState.getTexLevelParameteri(texture, level, pname);
|
||||
}
|
||||
|
||||
public static void bindImageTexture(int unit, int texture, int level, boolean layered, int layer, int access, int format) {
|
||||
GLStateManager.glBindImageTexture(unit, texture, level, layered, layer, access, format);
|
||||
GLSMTextures.glBindImageTexture(unit, texture, level, layered, layer, access, format);
|
||||
}
|
||||
|
||||
public static int getMaxImageUnits() {
|
||||
@@ -392,14 +439,14 @@ public class RenderSystem {
|
||||
return supportsImageLoadStore;
|
||||
}
|
||||
|
||||
public static boolean hasClipCullDistance() {
|
||||
return hasClipCullDistance;
|
||||
public static boolean isClipDistanceEmulated() {
|
||||
return clipDistanceEmulated;
|
||||
}
|
||||
|
||||
private static boolean hasExtension(String name) {
|
||||
final int count = GLStateManager.glGetInteger(GL30.GL_NUM_EXTENSIONS);
|
||||
static boolean hasExtension(String name) {
|
||||
final int count = GLSMQueries.glGetInteger(GL30.GL_NUM_EXTENSIONS);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (name.equals(GLStateManager.glGetStringi(GL11.GL_EXTENSIONS, i))) return true;
|
||||
if (name.equals(GLSMQueries.glGetStringi(GL11.GL_EXTENSIONS, i))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -459,31 +506,43 @@ public class RenderSystem {
|
||||
return supportsClearTexture;
|
||||
}
|
||||
|
||||
public static boolean supportsStencilTexturing() {
|
||||
return supportsStencilTexturing;
|
||||
}
|
||||
|
||||
public static boolean supportsTextureStorage() {
|
||||
return supportsTextureStorage;
|
||||
}
|
||||
|
||||
public static int getMaxSSBOBindings() {
|
||||
return maxSSBOBindings;
|
||||
}
|
||||
|
||||
public static void getProgramiv(int program, int value, IntBuffer storage) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.getProgramiv(program, value, storage);
|
||||
}
|
||||
|
||||
public static void dispatchCompute(int workX, int workY, int workZ) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.dispatchCompute(workX, workY, workZ);
|
||||
}
|
||||
|
||||
public static void dispatchCompute(Vector3i workGroups) {
|
||||
RENDER_BACKEND.dispatchCompute(workGroups.x, workGroups.y, workGroups.z);
|
||||
dispatchCompute(workGroups.x, workGroups.y, workGroups.z);
|
||||
}
|
||||
|
||||
public static void dispatchComputeIndirect(long offset) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.dispatchComputeIndirect(offset);
|
||||
}
|
||||
|
||||
public static void bindBuffer(int target, int buffer) {
|
||||
GLStateManager.glBindBuffer(target, buffer);
|
||||
GLSMBuffers.glBindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
public static void memoryBarrier(int barriers) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
if (supportsCompute) {
|
||||
RENDER_BACKEND.memoryBarrier(barriers);
|
||||
}
|
||||
@@ -494,57 +553,62 @@ public class RenderSystem {
|
||||
}
|
||||
|
||||
public static void disableBufferBlend(int buffer) {
|
||||
GLStateManager.glDisablei(GL11.GL_BLEND, buffer);
|
||||
GLSMEnable.glDisablei(GL11.GL_BLEND, buffer);
|
||||
}
|
||||
|
||||
public static void enableBufferBlend(int buffer) {
|
||||
GLStateManager.glEnablei(GL11.GL_BLEND, buffer);
|
||||
GLSMEnable.glEnablei(GL11.GL_BLEND, buffer);
|
||||
}
|
||||
|
||||
public static void blendFuncSeparatei(int buffer, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) {
|
||||
GLStateManager.glBlendFuncSeparatei(buffer, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
GLSMBlend.glBlendFuncSeparatei(buffer, srcRGB, dstRGB, srcAlpha, dstAlpha);
|
||||
}
|
||||
|
||||
public static void bindTextureToUnit(int unit, int texture) {
|
||||
if (unit != 0 && GLStateManager.getBoundTextureForServerState(unit) != texture) GLStateManager.beforeUncapturedStateChange();
|
||||
if (unit == 0) GLStateManager.recordExitTextureBind(GL11.GL_TEXTURE_2D, 0);
|
||||
else if (GLSMTextures.getBoundTextureForServerState(unit) != texture) GLStateManager.beforeUncapturedStateChange();
|
||||
dsaState.bindTextureToUnit(unit, texture);
|
||||
}
|
||||
|
||||
public static void bindTextureToUnit(int target, int unit, int texture) {
|
||||
if (unit != 0 && GLStateManager.getBoundTextureForServerState(unit) != texture) GLStateManager.beforeUncapturedStateChange();
|
||||
if (unit == 0) GLStateManager.recordExitTextureBind(target, 0);
|
||||
else if (GLSMTextures.getBoundTextureForServerState(unit) != texture) GLStateManager.beforeUncapturedStateChange();
|
||||
dsaState.bindTextureToUnit(target, unit, texture);
|
||||
}
|
||||
|
||||
public static void setupProjectionMatrix(Matrix4f matrix) {
|
||||
final FloatBuffer projectionMatrixBuffer = GLStateManager.ctx().projectionMatrixBuffer;
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GLStateManager.glPushMatrix();
|
||||
GLSMMatrices.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GLSMMatrices.glPushMatrix();
|
||||
matrix.get(0, projectionMatrixBuffer);
|
||||
GLStateManager.glLoadMatrix(projectionMatrixBuffer);
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLSMMatrices.glLoadMatrix(projectionMatrixBuffer);
|
||||
GLSMMatrices.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
public static void restoreProjectionMatrix() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GLStateManager.glPopMatrix();
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLSMMatrices.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GLSMMatrices.glPopMatrix();
|
||||
GLSMMatrices.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
public static void blitFramebuffer(int source, int dest, int offsetX, int offsetY, int width, int height, int offsetX2, int offsetY2, int width2, int height2, int bufferChoice, int filter) {
|
||||
final boolean scissor = GLStateManager.glIsEnabled(GL11.GL_SCISSOR_TEST);
|
||||
if (scissor) GLStateManager.glDisable(GL11.GL_SCISSOR_TEST);
|
||||
GLStateManager.rejectExitCapture();
|
||||
final boolean scissor = GLSMEnable.glIsEnabled(GL11.GL_SCISSOR_TEST);
|
||||
if (scissor) GLSMEnable.glDisable(GL11.GL_SCISSOR_TEST);
|
||||
try {
|
||||
dsaState.blitFramebuffer(source, dest, offsetX, offsetY, width, height, offsetX2, offsetY2, width2, height2, bufferChoice, filter);
|
||||
} finally {
|
||||
if (scissor) GLStateManager.glEnable(GL11.GL_SCISSOR_TEST);
|
||||
if (scissor) GLSMEnable.glEnable(GL11.GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
public static int createFramebuffer() {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return dsaState.createFramebuffer();
|
||||
}
|
||||
|
||||
public static int createTexture(int target) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
return dsaState.createTexture(target);
|
||||
}
|
||||
|
||||
@@ -558,29 +622,30 @@ public class RenderSystem {
|
||||
}
|
||||
|
||||
public static int createBuffers() {
|
||||
return GLStateManager.glGenBuffers();
|
||||
return GLSMBuffers.glGenBuffers();
|
||||
}
|
||||
|
||||
public static int getIndexedBufferBinding(int target, int index) {
|
||||
return GLStateManager.getIndexedBufferBinding(target, index);
|
||||
GLStateManager.rejectExitCapture();
|
||||
return GLSMBuffers.getIndexedBufferBinding(target, index);
|
||||
}
|
||||
|
||||
public static void bindBufferBase(int target, int index, int buffer) {
|
||||
GLStateManager.glBindBufferBase(target, index, buffer);
|
||||
GLSMBuffers.glBindBufferBase(target, index, buffer);
|
||||
}
|
||||
|
||||
public static void bufferStorage(int target, long size, int flags) {
|
||||
GLStateManager.glBufferStorage(target, size, flags);
|
||||
GLSMBuffers.glBufferStorage(target, size, flags);
|
||||
}
|
||||
|
||||
public static void clearBufferSubData(int target, int internalFormat, long offset, long size, int format, int type, int[] data) {
|
||||
final ByteBuffer buf = BufferUtils.createByteBuffer(data.length * 4);
|
||||
buf.asIntBuffer().put(data);
|
||||
GLStateManager.glClearBufferSubData(target, internalFormat, offset, size, format, type, buf);
|
||||
GLSMBuffers.glClearBufferSubData(target, internalFormat, offset, size, format, type, buf);
|
||||
}
|
||||
|
||||
public static void deleteBuffers(int buffer) {
|
||||
GLStateManager.glDeleteBuffers(buffer);
|
||||
GLSMBuffers.glDeleteBuffers(buffer);
|
||||
}
|
||||
|
||||
public static long getVRAM() {
|
||||
@@ -593,6 +658,7 @@ public class RenderSystem {
|
||||
}
|
||||
|
||||
public static void clearTexImage(int texture, int target, int level, int format, int type) {
|
||||
GLStateManager.rejectExitCapture();
|
||||
RENDER_BACKEND.clearTexImage(texture, level, format, type);
|
||||
}
|
||||
|
||||
@@ -627,37 +693,32 @@ public class RenderSystem {
|
||||
|
||||
public static int genSampler() {
|
||||
if (!supportsSamplerObjects) return 0;
|
||||
return GLStateManager.glGenSamplers();
|
||||
return GLSMTextures.glGenSamplers();
|
||||
}
|
||||
|
||||
public static void destroySampler(int sampler) {
|
||||
if (!supportsSamplerObjects || sampler == 0) return;
|
||||
GLStateManager.glDeleteSamplers(sampler);
|
||||
GLSMTextures.glDeleteSamplers(sampler);
|
||||
}
|
||||
|
||||
public static void samplerParameteri(int sampler, int pname, int param) {
|
||||
if (!supportsSamplerObjects || sampler == 0) return;
|
||||
GLStateManager.glSamplerParameteri(sampler, pname, param);
|
||||
GLSMTextures.glSamplerParameteri(sampler, pname, param);
|
||||
}
|
||||
|
||||
public static void samplerParameterf(int sampler, int pname, float param) {
|
||||
if (!supportsSamplerObjects || sampler == 0) return;
|
||||
GLStateManager.glSamplerParameterf(sampler, pname, param);
|
||||
GLSMTextures.glSamplerParameterf(sampler, pname, param);
|
||||
}
|
||||
|
||||
public static void bindSamplerToUnit(int unit, int sampler) {
|
||||
if (!supportsSamplerObjects) return;
|
||||
GLStateManager.glBindSampler(unit, sampler);
|
||||
GLSMTextures.glBindSampler(unit, sampler);
|
||||
}
|
||||
|
||||
public static void unbindAllSamplers() {
|
||||
if (!supportsSamplerObjects) return;
|
||||
final int count = GLStateManager.getSamplerUnitCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (GLStateManager.getSamplerBinding(i) != 0) {
|
||||
GLStateManager.glBindSampler(i, 0);
|
||||
}
|
||||
}
|
||||
GLSMTextures.unbindAllSamplers();
|
||||
}
|
||||
|
||||
/** Parse a GL version string (e.g. "4.6.0 NVIDIA ...") into concatenated digits "460". Strips
|
||||
|
||||
@@ -49,7 +49,7 @@ public final class StateSet {
|
||||
this.restore = restore;
|
||||
this.bump = bump;
|
||||
this.blendSnapshot = blendSnapshot;
|
||||
this.pushCommand = () -> GLStateManager.pushStateLive(this);
|
||||
this.pushCommand = () -> GLSMAttribStack.pushStateLive(this);
|
||||
}
|
||||
|
||||
public boolean contains(int id) {
|
||||
@@ -83,18 +83,18 @@ public final class StateSet {
|
||||
private static StateSet buildBatch() {
|
||||
return new StateSet(0,
|
||||
ids(
|
||||
GLStateManager.getBlendState(), GLStateManager.getAlphaState(), GLStateManager.getDepthState(),
|
||||
GLStateManager.getColorMask(), GLStateManager.getPolygonState(),
|
||||
GLStateManager.getTextures().getTextureUnitBindings(0), GLStateManager.getTextures().getTextureUnitBindings(1),
|
||||
GLStateManager.getActiveTextureUnitStack(),
|
||||
GLStateManager.getBlendMode(), GLStateManager.getAlphaTest(), GLStateManager.getDepthTest(),
|
||||
GLStateManager.getLightingState(), GLStateManager.getCullState(), GLStateManager.getPolygonOffsetFillState(),
|
||||
GLStateManager.getTextures().getTextureUnitStates(0), GLStateManager.getTextures().getTextureUnitStates(1),
|
||||
GLStateManager.getLightStates()[0], GLStateManager.getLightStates()[1],
|
||||
GLStateManager.getLightDataStates()[0], GLStateManager.getLightDataStates()[1],
|
||||
GLStateManager.getColorMaterial(), GLStateManager.getColorMaterialFace(), GLStateManager.getColorMaterialParameter(),
|
||||
GLStateManager.getLightModel(), GLStateManager.getFrontMaterial(), GLStateManager.getBackMaterial(),
|
||||
GLStateManager.getNormalizeState(), GLStateManager.getRescaleNormalState()
|
||||
GLSMBlend.getBlendState(), GLSMDepthStencilAlpha.getAlphaState(), GLSMDepthStencilAlpha.getDepthState(),
|
||||
GLSMBlend.getColorMask(), GLSMRasterizer.getPolygonState(),
|
||||
GLSMTextures.getTextures().getTextureUnitBindings(0), GLSMTextures.getTextures().getTextureUnitBindings(1),
|
||||
GLSMTextures.getActiveTextureUnitStack(),
|
||||
GLSMBlend.getBlendMode(), GLSMDepthStencilAlpha.getAlphaTest(), GLSMDepthStencilAlpha.getDepthTest(),
|
||||
GLSMLighting.getLightingState(), GLSMRasterizer.getCullState(), GLSMRasterizer.getPolygonOffsetFillState(),
|
||||
GLSMTextures.getTextures().getTextureUnitStates(0), GLSMTextures.getTextures().getTextureUnitStates(1),
|
||||
GLSMLighting.getLightStates()[0], GLSMLighting.getLightStates()[1],
|
||||
GLSMLighting.getLightDataStates()[0], GLSMLighting.getLightDataStates()[1],
|
||||
GLSMLighting.getColorMaterial(), GLSMLighting.getColorMaterialFace(), GLSMLighting.getColorMaterialParameter(),
|
||||
GLSMLighting.getLightModel(), GLSMLighting.getFrontMaterial(), GLSMLighting.getBackMaterial(),
|
||||
GLSMLighting.getNormalizeState(), GLSMLighting.getRescaleNormalState()
|
||||
),
|
||||
R_BLEND | R_DEPTH | R_COLOR_MASK | R_POLYGON | R_TEXTURE | R_ACTIVE_UNIT,
|
||||
B_FRAG_COLORBUF | B_LIGHTING,
|
||||
@@ -104,13 +104,13 @@ public final class StateSet {
|
||||
private static StateSet buildFont() {
|
||||
return new StateSet(0,
|
||||
ids(
|
||||
GLStateManager.getBlendState(), GLStateManager.getDepthState(), GLStateManager.getShadeModelState(),
|
||||
GLStateManager.getTextures().getTextureUnitBindings(0), GLStateManager.getTextures().getTextureUnitBindings(1),
|
||||
GLStateManager.getActiveTextureUnitStack(), GLStateManager.getProgramStack(),
|
||||
GLStateManager.getBlendMode(), GLStateManager.getAlphaTest(), GLStateManager.getDepthTest(),
|
||||
GLStateManager.getTextures().getTextureUnitStates(0),
|
||||
GLStateManager.getColorMask(), GLStateManager.getCullState(),
|
||||
GLStateManager.getPolygonState(), GLStateManager.getPolygonOffsetFillState()
|
||||
GLSMBlend.getBlendState(), GLSMDepthStencilAlpha.getDepthState(), GLSMRasterizer.getShadeModelState(),
|
||||
GLSMTextures.getTextures().getTextureUnitBindings(0), GLSMTextures.getTextures().getTextureUnitBindings(1),
|
||||
GLSMTextures.getActiveTextureUnitStack(), GLSMPrograms.getProgramStack(),
|
||||
GLSMBlend.getBlendMode(), GLSMDepthStencilAlpha.getAlphaTest(), GLSMDepthStencilAlpha.getDepthTest(),
|
||||
GLSMTextures.getTextures().getTextureUnitStates(0),
|
||||
GLSMBlend.getColorMask(), GLSMRasterizer.getCullState(),
|
||||
GLSMRasterizer.getPolygonState(), GLSMRasterizer.getPolygonOffsetFillState()
|
||||
),
|
||||
R_BLEND | R_DEPTH | R_COLOR_MASK | R_TEXTURE | R_ACTIVE_UNIT | R_PROGRAM | R_POLYGON,
|
||||
0,
|
||||
@@ -120,13 +120,13 @@ public final class StateSet {
|
||||
private static StateSet buildFontPipeline() {
|
||||
return new StateSet(0,
|
||||
ids(
|
||||
GLStateManager.getBlendState(), GLStateManager.getDepthState(),
|
||||
GLStateManager.getTextures().getTextureUnitBindings(0), GLStateManager.getTextures().getTextureUnitBindings(1),
|
||||
GLStateManager.getActiveTextureUnitStack(),
|
||||
GLStateManager.getBlendMode(), GLStateManager.getAlphaTest(), GLStateManager.getDepthTest(),
|
||||
GLStateManager.getTextures().getTextureUnitStates(0),
|
||||
GLStateManager.getColorMask(), GLStateManager.getCullState(),
|
||||
GLStateManager.getPolygonState(), GLStateManager.getPolygonOffsetFillState()
|
||||
GLSMBlend.getBlendState(), GLSMDepthStencilAlpha.getDepthState(),
|
||||
GLSMTextures.getTextures().getTextureUnitBindings(0), GLSMTextures.getTextures().getTextureUnitBindings(1),
|
||||
GLSMTextures.getActiveTextureUnitStack(),
|
||||
GLSMBlend.getBlendMode(), GLSMDepthStencilAlpha.getAlphaTest(), GLSMDepthStencilAlpha.getDepthTest(),
|
||||
GLSMTextures.getTextures().getTextureUnitStates(0),
|
||||
GLSMBlend.getColorMask(), GLSMRasterizer.getCullState(),
|
||||
GLSMRasterizer.getPolygonState(), GLSMRasterizer.getPolygonOffsetFillState()
|
||||
),
|
||||
R_BLEND | R_DEPTH | R_COLOR_MASK | R_TEXTURE | R_ACTIVE_UNIT | R_POLYGON,
|
||||
0,
|
||||
@@ -136,8 +136,8 @@ public final class StateSet {
|
||||
private static StateSet buildHand() {
|
||||
return new StateSet(0,
|
||||
ids(
|
||||
GLStateManager.getBlendState(), GLStateManager.getAlphaState(), GLStateManager.getDepthState(),
|
||||
GLStateManager.getBlendMode(), GLStateManager.getAlphaTest(), GLStateManager.getTextures().getTextureUnitStates(1)
|
||||
GLSMBlend.getBlendState(), GLSMDepthStencilAlpha.getAlphaState(), GLSMDepthStencilAlpha.getDepthState(),
|
||||
GLSMBlend.getBlendMode(), GLSMDepthStencilAlpha.getAlphaTest(), GLSMTextures.getTextures().getTextureUnitStates(1)
|
||||
),
|
||||
R_BLEND | R_DEPTH,
|
||||
B_FRAG_COLORBUF,
|
||||
@@ -146,7 +146,7 @@ public final class StateSet {
|
||||
|
||||
private static StateSet buildBlend() {
|
||||
return new StateSet(0,
|
||||
ids(GLStateManager.getBlendState(), GLStateManager.getBlendMode()),
|
||||
ids(GLSMBlend.getBlendState(), GLSMBlend.getBlendMode()),
|
||||
R_BLEND,
|
||||
0,
|
||||
true);
|
||||
@@ -154,7 +154,7 @@ public final class StateSet {
|
||||
|
||||
private static StateSet buildAlpha() {
|
||||
return new StateSet(0,
|
||||
ids(GLStateManager.getAlphaState(), GLStateManager.getAlphaTest()),
|
||||
ids(GLSMDepthStencilAlpha.getAlphaState(), GLSMDepthStencilAlpha.getAlphaTest()),
|
||||
0,
|
||||
B_FRAG_COLORBUF,
|
||||
false);
|
||||
@@ -162,7 +162,7 @@ public final class StateSet {
|
||||
|
||||
private static StateSet buildCutout() {
|
||||
return new StateSet(0,
|
||||
ids(GLStateManager.getAlphaState(), GLStateManager.getAlphaTest(), GLStateManager.getTextures().getTextureUnitStates(1)),
|
||||
ids(GLSMDepthStencilAlpha.getAlphaState(), GLSMDepthStencilAlpha.getAlphaTest(), GLSMTextures.getTextures().getTextureUnitStates(1)),
|
||||
0,
|
||||
B_FRAG_COLORBUF,
|
||||
false);
|
||||
@@ -170,7 +170,7 @@ public final class StateSet {
|
||||
|
||||
private static StateSet buildMasks() {
|
||||
return new StateSet(0,
|
||||
ids(GLStateManager.getDepthState(), GLStateManager.getColorMask()),
|
||||
ids(GLSMDepthStencilAlpha.getDepthState(), GLSMBlend.getColorMask()),
|
||||
R_DEPTH | R_COLOR_MASK,
|
||||
0,
|
||||
false);
|
||||
@@ -178,7 +178,7 @@ public final class StateSet {
|
||||
|
||||
private static StateSet buildCull() {
|
||||
return new StateSet(0,
|
||||
ids(GLStateManager.getPolygonState(), GLStateManager.getCullState()),
|
||||
ids(GLSMRasterizer.getPolygonState(), GLSMRasterizer.getCullState()),
|
||||
R_POLYGON,
|
||||
0,
|
||||
false);
|
||||
|
||||
+27
-1
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm.backend;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLScreenCapture;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import org.lwjgl.BufferUtils;
|
||||
@@ -42,6 +43,9 @@ import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.ShortBuffer;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetAddress;
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memGetInt;
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.Pointer.POINTER_SIZE;
|
||||
import static org.taumc.celeritas.lwjgl.LWJGLServiceProvider.LWJGL;
|
||||
|
||||
/**
|
||||
@@ -380,7 +384,9 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
|
||||
@Override
|
||||
public void multiDrawElementsBaseVertex(int mode, long pCount, int type, long pIndices, int drawcount, long pBaseVertex) {
|
||||
throw new UnsupportedOperationException("GLRenderBackend.multiDrawElementsBaseVertex should not be called — LWJGL service handles this");
|
||||
for (int i = 0; i < drawcount; i++) {
|
||||
GL32.glDrawElementsBaseVertex(mode, memGetInt(pCount + 4L * i), type, memGetAddress(pIndices + (long) i * POINTER_SIZE), memGetInt(pBaseVertex + 4L * i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -609,6 +615,21 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL30.glFramebufferTexture2D(target, attachment, textarget, texture, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void framebufferTexture1D(int target, int attachment, int textarget, int texture, int level) {
|
||||
GL30.glFramebufferTexture1D(target, attachment, textarget, texture, level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void framebufferTexture3D(int target, int attachment, int textarget, int texture, int level, int zoffset) {
|
||||
GL30.glFramebufferTexture3D(target, attachment, textarget, texture, level, zoffset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void framebufferTextureLayer(int target, int attachment, int texture, int level, int layer) {
|
||||
GL30.glFramebufferTextureLayer(target, attachment, texture, level, layer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void framebufferTexture(int target, int attachment, int texture, int level) {
|
||||
GL32.glFramebufferTexture(target, attachment, texture, level);
|
||||
@@ -639,6 +660,11 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL11.glReadBuffer(mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScreenCapture createScreenCapture(int width, int height) {
|
||||
return new GLScreenCapture(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readPixels(int x, int y, int width, int height, int format, int type, ByteBuffer pixels) {
|
||||
GL11.glReadPixels(x, y, width, height, format, type, pixels);
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.glsm.backend;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||
import com.gtnewhorizons.angelica.glsm.GLESFormatRemap;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMAttribStack;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureStaging;
|
||||
@@ -26,6 +27,8 @@ import java.util.function.Predicate;
|
||||
*/
|
||||
public abstract class RenderBackend {
|
||||
|
||||
public static final int MAX_FRAMES_IN_FLIGHT = 3;
|
||||
|
||||
public void onPostWindowCreate(long window) {}
|
||||
|
||||
public abstract void init();
|
||||
@@ -99,7 +102,7 @@ public abstract class RenderBackend {
|
||||
|
||||
static VSyncMode resolveTearFreeMode(VSyncMode preferred, Predicate<VSyncMode> supported) {
|
||||
if (preferred != null && preferred.tearFree() && supported.test(preferred)) return preferred;
|
||||
return supported.test(VSyncMode.MAILBOX) ? VSyncMode.MAILBOX : VSyncMode.ON;
|
||||
return VSyncMode.ON;
|
||||
}
|
||||
|
||||
protected abstract VSyncMode applyVSyncMode(VSyncMode preferred);
|
||||
@@ -247,7 +250,7 @@ public abstract class RenderBackend {
|
||||
|
||||
public void onFrameBegin() {
|
||||
if (GLStateManager.takeStateSeedPending()) {
|
||||
GLStateManager.replayStateToBackend();
|
||||
GLSMAttribStack.replayStateToBackend();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,6 +460,9 @@ public abstract class RenderBackend {
|
||||
public abstract void deleteFramebuffers(int framebuffer);
|
||||
public abstract void bindFramebuffer(int target, int framebuffer);
|
||||
public abstract void framebufferTexture2D(int target, int attachment, int textarget, int texture, int level);
|
||||
public abstract void framebufferTexture1D(int target, int attachment, int textarget, int texture, int level);
|
||||
public abstract void framebufferTexture3D(int target, int attachment, int textarget, int texture, int level, int zoffset);
|
||||
public abstract void framebufferTextureLayer(int target, int attachment, int texture, int level, int layer);
|
||||
public abstract void framebufferTexture(int target, int attachment, int texture, int level);
|
||||
public abstract int genRenderbuffers();
|
||||
public abstract void deleteRenderbuffers(int renderbuffer);
|
||||
@@ -473,6 +479,7 @@ public abstract class RenderBackend {
|
||||
public abstract void readPixels(int x, int y, int width, int height, int format, int type, FloatBuffer pixels);
|
||||
public abstract void readPixels(int x, int y, int width, int height, int format, int type, IntBuffer pixels);
|
||||
public abstract void readPixels(int x, int y, int width, int height, int format, int type, long pixelBufferOffset);
|
||||
public abstract ScreenCapture createScreenCapture(int width, int height);
|
||||
public abstract void getTexImage(int target, int level, int format, int type, ByteBuffer pixels);
|
||||
public abstract void getTexImage(int target, int level, int format, int type, IntBuffer pixels);
|
||||
public abstract void getTexImage(int target, int level, int format, int type, long pixelBufferOffset);
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.gtnewhorizons.angelica.glsm.backend;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
/** Async downscaled RGBA8 copy of a framebuffer's color. */
|
||||
public abstract class ScreenCapture {
|
||||
|
||||
public static final int RING = RenderBackend.MAX_FRAMES_IN_FLIGHT + 2;
|
||||
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final long[] tags = new long[RING];
|
||||
private final long[] syncs = new long[RING];
|
||||
private int head;
|
||||
private int tail;
|
||||
private long mapped;
|
||||
private boolean deleted;
|
||||
|
||||
protected ScreenCapture(int width, int height) {
|
||||
if (width <= 0 || height <= 0) throw new IllegalArgumentException("capture size " + width + "x" + height);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public final int width() { return width; }
|
||||
public final int height() { return height; }
|
||||
|
||||
public final boolean idle() { return head == tail; }
|
||||
|
||||
public final boolean begin(int srcFramebuffer, int srcWidth, int srcHeight, long tag) {
|
||||
if (deleted || head - tail == RING || srcWidth <= 0 || srcHeight <= 0) return false;
|
||||
final int slot = head % RING;
|
||||
if (!start(slot, srcFramebuffer, srcWidth, srcHeight)) return false;
|
||||
final long sync = GLSMBuffers.glFenceSync(GL32.GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
if (sync == 0L) return false;
|
||||
syncs[slot] = sync;
|
||||
tags[slot] = tag;
|
||||
head++;
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean poll() {
|
||||
if (mapped != 0L) throw new IllegalStateException("poll() before release() of the previous capture");
|
||||
while (tail != head) {
|
||||
final int slot = tail % RING;
|
||||
final int status = GLSMBuffers.glClientWaitSync(syncs[slot], 0, 0L);
|
||||
if (status == GL32.GL_TIMEOUT_EXPIRED) return false;
|
||||
dropSync(slot);
|
||||
if (status != GL32.GL_WAIT_FAILED) {
|
||||
mapped = map(slot);
|
||||
if (mapped != 0L) return true;
|
||||
}
|
||||
tail++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final long address() {
|
||||
if (mapped == 0L) throw new IllegalStateException("no polled capture");
|
||||
return mapped;
|
||||
}
|
||||
|
||||
public final long tag() {
|
||||
if (mapped == 0L) throw new IllegalStateException("no polled capture");
|
||||
return tags[tail % RING];
|
||||
}
|
||||
|
||||
public final void release() {
|
||||
if (mapped == 0L) throw new IllegalStateException("no polled capture");
|
||||
mapped = 0L;
|
||||
unmap(tail % RING);
|
||||
tail++;
|
||||
}
|
||||
|
||||
public final void delete() {
|
||||
if (deleted) return;
|
||||
if (mapped != 0L) release();
|
||||
deleted = true;
|
||||
for (int slot = 0; slot < RING; slot++) {
|
||||
dropSync(slot);
|
||||
deleteSlot(slot);
|
||||
}
|
||||
head = tail = 0;
|
||||
}
|
||||
|
||||
private void dropSync(int slot) {
|
||||
if (syncs[slot] == 0L) return;
|
||||
GLSMBuffers.glDeleteSync(syncs[slot]);
|
||||
syncs[slot] = 0L;
|
||||
}
|
||||
|
||||
/** Returns false when nothing was recorded; the slot then stays free. */
|
||||
protected abstract boolean start(int slot, int srcFramebuffer, int srcWidth, int srcHeight);
|
||||
|
||||
protected abstract long map(int slot);
|
||||
|
||||
protected abstract void unmap(int slot);
|
||||
|
||||
/** Called for every slot, including ones never started. */
|
||||
protected abstract void deleteSlot(int slot);
|
||||
}
|
||||
+3
-2
@@ -11,13 +11,14 @@ import java.util.function.IntSupplier;
|
||||
* @param samplerNames samplers the graphics program may not have, because only the stripped writes read them
|
||||
* @param samplerUnits per sampler name, the texture unit it reads at each draw, or -1 to use samplerTextures
|
||||
* @param samplerTextures per sampler name, its texture when samplerUnits is -1
|
||||
* @param samplerObjects per sampler name, the GL sampler object to sample it with when samplerUnits is -1, or 0
|
||||
* @param samplerObjects per sampler name, supplies its current GL sampler object when samplerUnits is -1;
|
||||
* null for unassigned or external bindings, and returns 0 to use the texture's own filtering
|
||||
* @param vertexBufferBinding storage buffer binding of the first vertex buffer the replay program declares
|
||||
* @param vertexBufferCount how many vertex buffers it declares, at consecutive bindings
|
||||
* @param indexBufferBinding storage buffer binding of its index buffer
|
||||
*/
|
||||
public record VertexWriteReplaySetup(int replayProgram, String[] inputNames, int[] inputLocations,
|
||||
IntSupplier[] images, int writtenImageCount,
|
||||
String[] samplerNames, int[] samplerUnits, IntSupplier[] samplerTextures, int[] samplerObjects,
|
||||
String[] samplerNames, int[] samplerUnits, IntSupplier[] samplerTextures, IntSupplier[] samplerObjects,
|
||||
int vertexBufferBinding, int vertexBufferCount, int indexBufferBinding) {
|
||||
}
|
||||
+24
-23
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.compat.lwjgl;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMDraws;
|
||||
import org.lwjgl.util.glu.Cylinder;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_LINES;
|
||||
@@ -28,11 +29,11 @@ public class AngelicaCylinder extends Cylinder {
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
}
|
||||
GLStateManager.glNormal3f(x, y, z);
|
||||
GLSMCurrentAttribs.glNormal3f(x, y, z);
|
||||
}
|
||||
|
||||
private void emitTexCoord(float x, float y) {
|
||||
if (super.textureFlag) GLStateManager.glTexCoord2f(x, y);
|
||||
if (super.textureFlag) GLSMCurrentAttribs.glTexCoord2f(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,7 +49,7 @@ public class AngelicaCylinder extends Cylinder {
|
||||
nz = (baseRadius - topRadius) / height;
|
||||
|
||||
if (super.drawStyle == GLU_POINT) {
|
||||
GLStateManager.glBegin(GL_POINTS);
|
||||
GLSMDraws.glBegin(GL_POINTS);
|
||||
for (int i = 0; i < slices; i++) {
|
||||
x = cos(i * da);
|
||||
y = sin(i * da);
|
||||
@@ -57,60 +58,60 @@ public class AngelicaCylinder extends Cylinder {
|
||||
z = 0.0f;
|
||||
r = baseRadius;
|
||||
for (int j = 0; j <= stacks; j++) {
|
||||
GLStateManager.glVertex3f(x * r, y * r, z);
|
||||
GLSMDraws.glVertex3f(x * r, y * r, z);
|
||||
z += dz;
|
||||
r += dr;
|
||||
}
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
} else if (super.drawStyle == GLU_LINE || super.drawStyle == GLU_SILHOUETTE) {
|
||||
// Draw rings
|
||||
if (super.drawStyle == GLU_LINE) {
|
||||
z = 0.0f;
|
||||
r = baseRadius;
|
||||
for (int j = 0; j <= stacks; j++) {
|
||||
GLStateManager.glBegin(GL_LINE_LOOP);
|
||||
GLSMDraws.glBegin(GL_LINE_LOOP);
|
||||
for (int i = 0; i < slices; i++) {
|
||||
x = cos(i * da);
|
||||
y = sin(i * da);
|
||||
emitNormal(x * nsign, y * nsign, nz * nsign);
|
||||
GLStateManager.glVertex3f(x * r, y * r, z);
|
||||
GLSMDraws.glVertex3f(x * r, y * r, z);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
z += dz;
|
||||
r += dr;
|
||||
}
|
||||
} else {
|
||||
// draw one ring at each end
|
||||
if (baseRadius != 0.0) {
|
||||
GLStateManager.glBegin(GL_LINE_LOOP);
|
||||
GLSMDraws.glBegin(GL_LINE_LOOP);
|
||||
for (int i = 0; i < slices; i++) {
|
||||
x = cos(i * da);
|
||||
y = sin(i * da);
|
||||
emitNormal(x * nsign, y * nsign, nz * nsign);
|
||||
GLStateManager.glVertex3f(x * baseRadius, y * baseRadius, 0.0f);
|
||||
GLSMDraws.glVertex3f(x * baseRadius, y * baseRadius, 0.0f);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLStateManager.glBegin(GL_LINE_LOOP);
|
||||
GLSMDraws.glEnd();
|
||||
GLSMDraws.glBegin(GL_LINE_LOOP);
|
||||
for (int i = 0; i < slices; i++) {
|
||||
x = cos(i * da);
|
||||
y = sin(i * da);
|
||||
emitNormal(x * nsign, y * nsign, nz * nsign);
|
||||
GLStateManager.glVertex3f(x * topRadius, y * topRadius, height);
|
||||
GLSMDraws.glVertex3f(x * topRadius, y * topRadius, height);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
}
|
||||
// draw length lines
|
||||
GLStateManager.glBegin(GL_LINES);
|
||||
GLSMDraws.glBegin(GL_LINES);
|
||||
for (int i = 0; i < slices; i++) {
|
||||
x = cos(i * da);
|
||||
y = sin(i * da);
|
||||
emitNormal(x * nsign, y * nsign, nz * nsign);
|
||||
GLStateManager.glVertex3f(x * baseRadius, y * baseRadius, 0.0f);
|
||||
GLStateManager.glVertex3f(x * topRadius, y * topRadius, height);
|
||||
GLSMDraws.glVertex3f(x * baseRadius, y * baseRadius, 0.0f);
|
||||
GLSMDraws.glVertex3f(x * topRadius, y * topRadius, height);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
} else if (super.drawStyle == GLU_FILL) {
|
||||
final float ds = 1.0f / slices;
|
||||
final float dt = 1.0f / stacks;
|
||||
@@ -119,20 +120,20 @@ public class AngelicaCylinder extends Cylinder {
|
||||
r = baseRadius;
|
||||
for (int j = 0; j < stacks; j++) {
|
||||
float s = 0.0f;
|
||||
GLStateManager.glBegin(GL_TRIANGLE_STRIP);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_STRIP);
|
||||
for (int i = 0; i <= slices; i++) {
|
||||
final float angle = (i == slices) ? 0.0f : i * da;
|
||||
x = sin(angle);
|
||||
y = cos(angle);
|
||||
emitNormal(x * nsign, y * nsign, nz * nsign);
|
||||
emitTexCoord(s, t);
|
||||
GLStateManager.glVertex3f(x * r, y * r, z);
|
||||
GLSMDraws.glVertex3f(x * r, y * r, z);
|
||||
emitNormal(x * nsign, y * nsign, nz * nsign);
|
||||
emitTexCoord(s, t + dt);
|
||||
GLStateManager.glVertex3f(x * (r + dr), y * (r + dr), z + dz);
|
||||
GLSMDraws.glVertex3f(x * (r + dr), y * (r + dr), z + dz);
|
||||
s += ds;
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
r += dr;
|
||||
t += dt;
|
||||
z += dz;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.compat.lwjgl;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMDraws;
|
||||
import org.lwjgl.util.glu.Disk;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_LINE_LOOP;
|
||||
@@ -23,7 +24,7 @@ public class AngelicaDisk extends Disk {
|
||||
private static final float PI = (float) Math.PI;
|
||||
|
||||
private void emitTexCoord(float x, float y) {
|
||||
if (super.textureFlag) GLStateManager.glTexCoord2f(x, y);
|
||||
if (super.textureFlag) GLSMCurrentAttribs.glTexCoord2f(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,7 +32,7 @@ public class AngelicaDisk extends Disk {
|
||||
final float da, dr;
|
||||
|
||||
if (super.normals != GLU_NONE) {
|
||||
GLStateManager.glNormal3f(0.0f, 0.0f, (super.orientation == GLU_OUTSIDE) ? 1.0f : -1.0f);
|
||||
GLSMCurrentAttribs.glNormal3f(0.0f, 0.0f, (super.orientation == GLU_OUTSIDE) ? 1.0f : -1.0f);
|
||||
}
|
||||
|
||||
da = 2.0f * PI / slices;
|
||||
@@ -45,29 +46,29 @@ public class AngelicaDisk extends Disk {
|
||||
for (int l = 0; l < loops; l++) {
|
||||
final float r2 = r1 + dr;
|
||||
if (super.orientation == GLU_OUTSIDE) {
|
||||
GLStateManager.glBegin(GL_TRIANGLE_STRIP);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_STRIP);
|
||||
for (int s = 0; s <= slices; s++) {
|
||||
final float a = (s == slices) ? 0.0f : s * da;
|
||||
sa = sin(a);
|
||||
ca = cos(a);
|
||||
emitTexCoord(0.5f + sa * r2 / dtc, 0.5f + ca * r2 / dtc);
|
||||
GLStateManager.glVertex2f(r2 * sa, r2 * ca);
|
||||
GLSMDraws.glVertex2f(r2 * sa, r2 * ca);
|
||||
emitTexCoord(0.5f + sa * r1 / dtc, 0.5f + ca * r1 / dtc);
|
||||
GLStateManager.glVertex2f(r1 * sa, r1 * ca);
|
||||
GLSMDraws.glVertex2f(r1 * sa, r1 * ca);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
} else {
|
||||
GLStateManager.glBegin(GL_TRIANGLE_STRIP);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_STRIP);
|
||||
for (int s = slices; s >= 0; s--) {
|
||||
final float a = (s == slices) ? 0.0f : s * da;
|
||||
sa = sin(a);
|
||||
ca = cos(a);
|
||||
emitTexCoord(0.5f - sa * r2 / dtc, 0.5f + ca * r2 / dtc);
|
||||
GLStateManager.glVertex2f(r2 * sa, r2 * ca);
|
||||
GLSMDraws.glVertex2f(r2 * sa, r2 * ca);
|
||||
emitTexCoord(0.5f - sa * r1 / dtc, 0.5f + ca * r1 / dtc);
|
||||
GLStateManager.glVertex2f(r1 * sa, r1 * ca);
|
||||
GLSMDraws.glVertex2f(r1 * sa, r1 * ca);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
r1 = r2;
|
||||
}
|
||||
@@ -76,56 +77,56 @@ public class AngelicaDisk extends Disk {
|
||||
/* draw loops */
|
||||
for (int l = 0; l <= loops; l++) {
|
||||
final float r = innerRadius + l * dr;
|
||||
GLStateManager.glBegin(GL_LINE_LOOP);
|
||||
GLSMDraws.glBegin(GL_LINE_LOOP);
|
||||
for (int s = 0; s < slices; s++) {
|
||||
final float a = s * da;
|
||||
GLStateManager.glVertex2f(r * sin(a), r * cos(a));
|
||||
GLSMDraws.glVertex2f(r * sin(a), r * cos(a));
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
/* draw spokes */
|
||||
for (int s = 0; s < slices; s++) {
|
||||
final float a = s * da;
|
||||
final float x = sin(a);
|
||||
final float y = cos(a);
|
||||
GLStateManager.glBegin(GL_LINE_STRIP);
|
||||
GLSMDraws.glBegin(GL_LINE_STRIP);
|
||||
for (int l = 0; l <= loops; l++) {
|
||||
final float r = innerRadius + l * dr;
|
||||
GLStateManager.glVertex2f(r * x, r * y);
|
||||
GLSMDraws.glVertex2f(r * x, r * y);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
}
|
||||
case GLU_POINT -> {
|
||||
GLStateManager.glBegin(GL_POINTS);
|
||||
GLSMDraws.glBegin(GL_POINTS);
|
||||
for (int s = 0; s < slices; s++) {
|
||||
final float a = s * da;
|
||||
final float x = sin(a);
|
||||
final float y = cos(a);
|
||||
for (int l = 0; l <= loops; l++) {
|
||||
final float r = innerRadius * l * dr;
|
||||
GLStateManager.glVertex2f(r * x, r * y);
|
||||
GLSMDraws.glVertex2f(r * x, r * y);
|
||||
}
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
case GLU_SILHOUETTE -> {
|
||||
if (innerRadius != 0.0) {
|
||||
GLStateManager.glBegin(GL_LINE_LOOP);
|
||||
GLSMDraws.glBegin(GL_LINE_LOOP);
|
||||
for (float a = 0.0f; a < 2.0 * PI; a += da) {
|
||||
final float x = innerRadius * sin(a);
|
||||
final float y = innerRadius * cos(a);
|
||||
GLStateManager.glVertex2f(x, y);
|
||||
GLSMDraws.glVertex2f(x, y);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
GLStateManager.glBegin(GL_LINE_LOOP);
|
||||
GLSMDraws.glBegin(GL_LINE_LOOP);
|
||||
for (float a = 0; a < 2.0f * PI; a += da) {
|
||||
final float x = outerRadius * sin(a);
|
||||
final float y = outerRadius * cos(a);
|
||||
GLStateManager.glVertex2f(x, y);
|
||||
GLSMDraws.glVertex2f(x, y);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
|
||||
+45
-43
@@ -1,5 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.compat.lwjgl;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMDraws;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.lwjgl.util.glu.PartialDisk;
|
||||
|
||||
@@ -63,7 +65,7 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
}
|
||||
|
||||
switch (super.normals) {
|
||||
case GLU_FLAT, GLU_SMOOTH -> GLStateManager.glNormal3f(0.0f, 0.0f, (super.orientation == GLU_OUTSIDE) ? 1.0f : -1.0f);
|
||||
case GLU_FLAT, GLU_SMOOTH -> GLSMCurrentAttribs.glNormal3f(0.0f, 0.0f, (super.orientation == GLU_OUTSIDE) ? 1.0f : -1.0f);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
@@ -73,11 +75,11 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
if (innerRadius == .0f) {
|
||||
finish = loops - 1;
|
||||
/* Triangle strip for inner polygons */
|
||||
GLStateManager.glBegin(GL_TRIANGLE_FAN);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_FAN);
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(0.5f, 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(0.5f, 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GLSMDraws.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
radiusLow = outerRadius - deltaRadius * ((float) (loops - 1) / loops);
|
||||
if (super.textureFlag) {
|
||||
texLow = radiusLow / outerRadius / 2;
|
||||
@@ -86,19 +88,19 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
if (super.orientation == GLU_OUTSIDE) {
|
||||
for (int i = slices; i >= 0; i--) {
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i <= slices; i++) {
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
}
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
} else {
|
||||
finish = loops;
|
||||
}
|
||||
@@ -110,35 +112,35 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
texHigh = radiusHigh / outerRadius / 2;
|
||||
}
|
||||
|
||||
GLStateManager.glBegin(GL_TRIANGLE_STRIP);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_STRIP);
|
||||
for (int i = 0; i <= slices; i++) {
|
||||
if (super.orientation == GLU_OUTSIDE) {
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texHigh * sinCache[i] + 0.5f, texHigh * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texHigh * sinCache[i] + 0.5f, texHigh * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusHigh * sinCache[i], radiusHigh * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusHigh * sinCache[i], radiusHigh * cosCache[i], 0.0f);
|
||||
} else {
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texHigh * sinCache[i] + 0.5f, texHigh * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texHigh * sinCache[i] + 0.5f, texHigh * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusHigh * sinCache[i], radiusHigh * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusHigh * sinCache[i], radiusHigh * cosCache[i], 0.0f);
|
||||
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
}
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
}
|
||||
case GLU_POINT -> {
|
||||
GLStateManager.glBegin(GL_POINTS);
|
||||
GLSMDraws.glBegin(GL_POINTS);
|
||||
for (int i = 0; i < slices2; i++) {
|
||||
sintemp = sinCache[i];
|
||||
costemp = cosCache[i];
|
||||
@@ -148,24 +150,24 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
if (super.textureFlag) {
|
||||
texLow = radiusLow / outerRadius / 2;
|
||||
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
|
||||
}
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
case GLU_LINE -> {
|
||||
if (innerRadius == outerRadius) {
|
||||
GLStateManager.glBegin(GL_LINE_STRIP);
|
||||
GLSMDraws.glBegin(GL_LINE_STRIP);
|
||||
|
||||
for (int i = 0; i <= slices; i++) {
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(sinCache[i] / 2 + 0.5f, cosCache[i] / 2 + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(sinCache[i] / 2 + 0.5f, cosCache[i] / 2 + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(innerRadius * sinCache[i], innerRadius * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(innerRadius * sinCache[i], innerRadius * cosCache[i], 0.0f);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
break;
|
||||
}
|
||||
for (int j = 0; j <= loops; j++) {
|
||||
@@ -174,19 +176,19 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
texLow = radiusLow / outerRadius / 2;
|
||||
}
|
||||
|
||||
GLStateManager.glBegin(GL_LINE_STRIP);
|
||||
GLSMDraws.glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i <= slices; i++) {
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
for (int i = 0; i < slices2; i++) {
|
||||
sintemp = sinCache[i];
|
||||
costemp = cosCache[i];
|
||||
GLStateManager.glBegin(GL_LINE_STRIP);
|
||||
GLSMDraws.glBegin(GL_LINE_STRIP);
|
||||
for (int j = 0; j <= loops; j++) {
|
||||
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
|
||||
if (super.textureFlag) {
|
||||
@@ -194,11 +196,11 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
}
|
||||
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
}
|
||||
case GLU_SILHOUETTE -> {
|
||||
@@ -206,17 +208,17 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
for (int i = 0; i <= slices; i += slices) {
|
||||
sintemp = sinCache[i];
|
||||
costemp = cosCache[i];
|
||||
GLStateManager.glBegin(GL_LINE_STRIP);
|
||||
GLSMDraws.glBegin(GL_LINE_STRIP);
|
||||
for (int j = 0; j <= loops; j++) {
|
||||
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
|
||||
|
||||
if (super.textureFlag) {
|
||||
texLow = radiusLow / outerRadius / 2;
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0f);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
}
|
||||
for (int j = 0; j <= loops; j += loops) {
|
||||
@@ -225,14 +227,14 @@ public class AngelicaPartialDisk extends PartialDisk {
|
||||
texLow = radiusLow / outerRadius / 2;
|
||||
}
|
||||
|
||||
GLStateManager.glBegin(GL_LINE_STRIP);
|
||||
GLSMDraws.glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i <= slices; i++) {
|
||||
if (super.textureFlag) {
|
||||
GLStateManager.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
GLSMCurrentAttribs.glTexCoord2f(texLow * sinCache[i] + 0.5f, texLow * cosCache[i] + 0.5f);
|
||||
}
|
||||
GLStateManager.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
GLSMDraws.glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
if (innerRadius == outerRadius) break;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-30
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.compat.lwjgl;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMDraws;
|
||||
import org.lwjgl.util.glu.Sphere;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_LINE_LOOP;
|
||||
@@ -30,11 +31,11 @@ public class AngelicaSphere extends Sphere {
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
}
|
||||
GLStateManager.glNormal3f(x, y, z);
|
||||
GLSMCurrentAttribs.glNormal3f(x, y, z);
|
||||
}
|
||||
|
||||
private void emitTexCoord(float x, float y) {
|
||||
if (super.textureFlag) GLStateManager.glTexCoord2f(x, y);
|
||||
if (super.textureFlag) GLSMCurrentAttribs.glTexCoord2f(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,9 +55,9 @@ public class AngelicaSphere extends Sphere {
|
||||
if (super.drawStyle == GLU_FILL) {
|
||||
if (!super.textureFlag) {
|
||||
// draw +Z end as a triangle fan
|
||||
GLStateManager.glBegin(GL_TRIANGLE_FAN);
|
||||
GLStateManager.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, nsign * radius);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_FAN);
|
||||
GLSMCurrentAttribs.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
GLSMDraws.glVertex3f(0.0f, 0.0f, nsign * radius);
|
||||
for (int j = 0; j <= slices; j++) {
|
||||
theta = (j == slices) ? 0.0f : j * dtheta;
|
||||
x = -sin(theta) * sin(drho);
|
||||
@@ -65,9 +66,9 @@ public class AngelicaSphere extends Sphere {
|
||||
if (normals) {
|
||||
emitNormal(x * nsign, y * nsign, z * nsign);
|
||||
}
|
||||
GLStateManager.glVertex3f(x * radius, y * radius, z * radius);
|
||||
GLSMDraws.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
|
||||
ds = 1.0f / slices;
|
||||
@@ -84,7 +85,7 @@ public class AngelicaSphere extends Sphere {
|
||||
// draw intermediate stacks as triangle strips (GL_QUAD_STRIP removed in core profile)
|
||||
for (int i = imin; i < imax; i++) {
|
||||
rho = i * drho;
|
||||
GLStateManager.glBegin(GL_TRIANGLE_STRIP);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_STRIP);
|
||||
s = 0.0f;
|
||||
for (int j = 0; j <= slices; j++) {
|
||||
theta = (j == slices) ? 0.0f : j * dtheta;
|
||||
@@ -95,7 +96,7 @@ public class AngelicaSphere extends Sphere {
|
||||
emitNormal(x * nsign, y * nsign, z * nsign);
|
||||
}
|
||||
emitTexCoord(s, t);
|
||||
GLStateManager.glVertex3f(x * radius, y * radius, z * radius);
|
||||
GLSMDraws.glVertex3f(x * radius, y * radius, z * radius);
|
||||
x = -sin(theta) * sin(rho + drho);
|
||||
y = cos(theta) * sin(rho + drho);
|
||||
z = nsign * cos(rho + drho);
|
||||
@@ -104,17 +105,17 @@ public class AngelicaSphere extends Sphere {
|
||||
}
|
||||
emitTexCoord(s, t - dt);
|
||||
s += ds;
|
||||
GLStateManager.glVertex3f(x * radius, y * radius, z * radius);
|
||||
GLSMDraws.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
t -= dt;
|
||||
}
|
||||
|
||||
if (!super.textureFlag) {
|
||||
// draw -Z end as a triangle fan
|
||||
GLStateManager.glBegin(GL_TRIANGLE_FAN);
|
||||
GLStateManager.glNormal3f(0.0f, 0.0f, -1.0f);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, -radius * nsign);
|
||||
GLSMDraws.glBegin(GL_TRIANGLE_FAN);
|
||||
GLSMCurrentAttribs.glNormal3f(0.0f, 0.0f, -1.0f);
|
||||
GLSMDraws.glVertex3f(0.0f, 0.0f, -radius * nsign);
|
||||
rho = PI - drho;
|
||||
s = 1.0f;
|
||||
for (int j = slices; j >= 0; j--) {
|
||||
@@ -124,46 +125,46 @@ public class AngelicaSphere extends Sphere {
|
||||
z = nsign * cos(rho);
|
||||
if (normals) emitNormal(x * nsign, y * nsign, z * nsign);
|
||||
s -= ds;
|
||||
GLStateManager.glVertex3f(x * radius, y * radius, z * radius);
|
||||
GLSMDraws.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
} else if (super.drawStyle == GLU_LINE || super.drawStyle == GLU_SILHOUETTE) {
|
||||
// draw stack lines
|
||||
for (int i = 1; i < stacks; i++) {
|
||||
rho = i * drho;
|
||||
GLStateManager.glBegin(GL_LINE_LOOP);
|
||||
GLSMDraws.glBegin(GL_LINE_LOOP);
|
||||
for (int j = 0; j < slices; j++) {
|
||||
theta = j * dtheta;
|
||||
x = cos(theta) * sin(rho);
|
||||
y = sin(theta) * sin(rho);
|
||||
z = cos(rho);
|
||||
if (normals) emitNormal(x * nsign, y * nsign, z * nsign);
|
||||
GLStateManager.glVertex3f(x * radius, y * radius, z * radius);
|
||||
GLSMDraws.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
// draw slice lines
|
||||
for (int j = 0; j < slices; j++) {
|
||||
theta = j * dtheta;
|
||||
GLStateManager.glBegin(GL_LINE_STRIP);
|
||||
GLSMDraws.glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i <= stacks; i++) {
|
||||
rho = i * drho;
|
||||
x = cos(theta) * sin(rho);
|
||||
y = sin(theta) * sin(rho);
|
||||
z = cos(rho);
|
||||
if (normals) emitNormal(x * nsign, y * nsign, z * nsign);
|
||||
GLStateManager.glVertex3f(x * radius, y * radius, z * radius);
|
||||
GLSMDraws.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
} else if (super.drawStyle == GLU_POINT) {
|
||||
// top and bottom-most points
|
||||
GLStateManager.glBegin(GL_POINTS);
|
||||
if (normals) GLStateManager.glNormal3f(0.0f, 0.0f, nsign);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, radius);
|
||||
if (normals) GLStateManager.glNormal3f(0.0f, 0.0f, -nsign);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, -radius);
|
||||
GLSMDraws.glBegin(GL_POINTS);
|
||||
if (normals) GLSMCurrentAttribs.glNormal3f(0.0f, 0.0f, nsign);
|
||||
GLSMDraws.glVertex3f(0.0f, 0.0f, radius);
|
||||
if (normals) GLSMCurrentAttribs.glNormal3f(0.0f, 0.0f, -nsign);
|
||||
GLSMDraws.glVertex3f(0.0f, 0.0f, -radius);
|
||||
|
||||
// loop over stacks
|
||||
for (int i = 1; i < stacks - 1; i++) {
|
||||
@@ -174,10 +175,10 @@ public class AngelicaSphere extends Sphere {
|
||||
y = sin(theta) * sin(rho);
|
||||
z = cos(rho);
|
||||
if (normals) emitNormal(x * nsign, y * nsign, z * nsign);
|
||||
GLStateManager.glVertex3f(x * radius, y * radius, z * radius);
|
||||
GLSMDraws.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
GLSMDraws.glEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.gtnewhorizons.angelica.glsm.dsa;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMFramebuffer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMTextures;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -42,23 +45,23 @@ public class DSAARB extends DSAUnsupported {
|
||||
|
||||
@Override
|
||||
public void texParameteri(int texture, int target, int pname, int param) {
|
||||
param = GLStateManager.remapTexClamp(pname, param);
|
||||
if(!GLStateManager.updateTexParameteriCache(target, texture, pname, param)) return;
|
||||
param = GLSMTextures.remapTexClamp(pname, param);
|
||||
if(!GLSMTextures.updateTexParameteriCache(target, texture, pname, param)) return;
|
||||
|
||||
RENDER_BACKEND.textureParameteri(texture, target, pname, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void texParameterf(int texture, int target, int pname, float param) {
|
||||
param = GLStateManager.remapTexClamp(pname, param);
|
||||
if(!GLStateManager.updateTexParameterfCache(target, texture, pname, param)) return;
|
||||
param = GLSMTextures.remapTexClamp(pname, param);
|
||||
if(!GLSMTextures.updateTexParameterfCache(target, texture, pname, param)) return;
|
||||
|
||||
RENDER_BACKEND.textureParameterf(texture, target, pname, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void texParameteriv(int texture, int target, int pname, IntBuffer params) {
|
||||
GLStateManager.remapTexClampBuffer(pname, params);
|
||||
GLSMTextures.remapTexClampBuffer(pname, params);
|
||||
RENDER_BACKEND.textureParameteriv(texture, target, pname, params);
|
||||
}
|
||||
|
||||
@@ -74,8 +77,8 @@ public class DSAARB extends DSAUnsupported {
|
||||
|
||||
@Override
|
||||
public int getTexParameteri(int texture, int target, int pname) {
|
||||
final long v = GLStateManager.lookupTexParameteri(TextureInfoCache.INSTANCE.getInfo(texture), pname);
|
||||
return v != GLStateManager.TEX_PARAM_MISS ? (int) v : RENDER_BACKEND.getTextureParameteri(texture, target, pname);
|
||||
final long v = GLSMTextures.lookupTexParameteri(TextureInfoCache.INSTANCE.getInfo(texture), pname);
|
||||
return v != GLSMTextures.TEX_PARAM_MISS ? (int) v : RENDER_BACKEND.getTextureParameteri(texture, target, pname);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,23 +103,23 @@ public class DSAARB extends DSAUnsupported {
|
||||
|
||||
@Override
|
||||
public void bindTextureToUnit(int target, int unit, int texture) {
|
||||
if(GLStateManager.getBoundTextureForServerState(unit) == texture) return;
|
||||
if(GLSMTextures.getBoundTextureForServerState(unit) == texture) return;
|
||||
|
||||
if (texture == 0) {
|
||||
super.bindTextureToUnit(target != 0 ? target : GL11.GL_TEXTURE_2D, unit, texture);
|
||||
} else {
|
||||
RENDER_BACKEND.bindTextureUnit(unit, texture);
|
||||
final var binding = GLStateManager.getTextures().getTextureUnitBindings(unit);
|
||||
final var binding = GLSMTextures.getTextures().getTextureUnitBindings(unit);
|
||||
binding.beforeModify();
|
||||
binding.setBinding(texture, target);
|
||||
GLStateManager.trackMaxBoundTextureUnit(unit);
|
||||
GLSMTextures.trackMaxBoundTextureUnit(unit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bufferStorage(int target, FloatBuffer data, int usage) {
|
||||
final int buffer = GLStateManager.glCreateBuffers();
|
||||
GLStateManager.glNamedBufferData(buffer, data, usage);
|
||||
final int buffer = GLSMBuffers.glCreateBuffers();
|
||||
GLSMBuffers.glNamedBufferData(buffer, data, usage);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -128,7 +131,7 @@ public class DSAARB extends DSAUnsupported {
|
||||
|
||||
@Override
|
||||
public void framebufferTexture2D(int fb, int fbtarget, int attachment, int target, int texture, int levels) {
|
||||
RENDER_BACKEND.namedFramebufferTexture(fb, attachment, texture, levels);
|
||||
GLSMFramebuffer.glNamedFramebufferTexture(fb, attachment, texture, levels);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,7 +142,6 @@ public class DSAARB extends DSAUnsupported {
|
||||
|
||||
@Override
|
||||
public int createTexture(int target) {
|
||||
GLStateManager.requireContext("glCreateTextures");
|
||||
return RENDER_BACKEND.createTextures(target);
|
||||
return GLSMTextures.glCreateTextures(target);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
package com.gtnewhorizons.angelica.glsm.dsa;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMFramebuffer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMTextures;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.TextureBindingStack;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureTargets;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
@@ -18,7 +20,7 @@ public class DSAUnsupported implements DSAAccess {
|
||||
|
||||
@Override
|
||||
public void generateMipmaps(int texture, int target) {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
GLSMTextures.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
RENDER_BACKEND.generateMipmap(target);
|
||||
}
|
||||
|
||||
@@ -57,40 +59,40 @@ public class DSAUnsupported implements DSAAccess {
|
||||
@Override
|
||||
public void texParameteri(int texture, int target, int pname, int param) {
|
||||
final int previous = bindForEdit(target, texture);
|
||||
GLStateManager.glTexParameteri(target, pname, param);
|
||||
GLSMTextures.glTexParameteri(target, pname, param);
|
||||
restoreBinding(target, previous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void texParameterf(int texture, int target, int pname, float param) {
|
||||
final int previous = bindForEdit(target, texture);
|
||||
GLStateManager.glTexParameterf(target, pname, param);
|
||||
GLSMTextures.glTexParameterf(target, pname, param);
|
||||
restoreBinding(target, previous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void texParameteriv(int texture, int target, int pname, IntBuffer params) {
|
||||
final int previous = bindForEdit(target, texture);
|
||||
GLStateManager.glTexParameter(target, pname, params);
|
||||
GLSMTextures.glTexParameter(target, pname, params);
|
||||
restoreBinding(target, previous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readBuffer(int framebuffer, int buffer) {
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_FRAMEBUFFER, framebuffer);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_FRAMEBUFFER, framebuffer);
|
||||
RENDER_BACKEND.readBuffer(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBuffers(int framebuffer, IntBuffer buffers) {
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_FRAMEBUFFER, framebuffer);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_FRAMEBUFFER, framebuffer);
|
||||
RENDER_BACKEND.drawBuffers(buffers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTexParameteri(int texture, int target, int pname) {
|
||||
final int previous = bindForEdit(target, texture);
|
||||
final int result = GLStateManager.glGetTexParameteri(target, pname);
|
||||
final int result = GLSMTextures.glGetTexParameteri(target, pname);
|
||||
restoreBinding(target, previous);
|
||||
return result;
|
||||
}
|
||||
@@ -98,7 +100,7 @@ public class DSAUnsupported implements DSAAccess {
|
||||
@Override
|
||||
public float getTexParameterf(int texture, int target, int pname) {
|
||||
final int previous = bindForEdit(target, texture);
|
||||
final float result = GLStateManager.glGetTexParameterf(target, pname);
|
||||
final float result = GLSMTextures.glGetTexParameterf(target, pname);
|
||||
restoreBinding(target, previous);
|
||||
return result;
|
||||
}
|
||||
@@ -115,29 +117,29 @@ public class DSAUnsupported implements DSAAccess {
|
||||
@Override
|
||||
public void copyTexSubImage2D(int destTexture, int target, int i, int i1, int i2, int i3, int i4, int width, int height) {
|
||||
final int previous = previous2D();
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, destTexture);
|
||||
GLSMTextures.glBindTexture(GL11.GL_TEXTURE_2D, destTexture);
|
||||
RENDER_BACKEND.copyTexSubImage2D(target, i, i1, i2, i3, i4, width, height);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, previous);
|
||||
GLSMTextures.glBindTexture(GL11.GL_TEXTURE_2D, previous);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindTextureToUnit(int unit, int texture) {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
GLSMTextures.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
GLSMTextures.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindTextureToUnit(int target, int unit, int texture) {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
GLStateManager.glBindTexture(target, texture);
|
||||
GLSMTextures.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
GLSMTextures.glBindTexture(target, texture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bufferStorage(int target, FloatBuffer data, int usage) {
|
||||
final int buffer = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(target, buffer);
|
||||
GLStateManager.glBufferData(target, data, usage);
|
||||
GLStateManager.glBindBuffer(target, 0);
|
||||
final int buffer = GLSMBuffers.glGenBuffers();
|
||||
GLSMBuffers.glBindBuffer(target, buffer);
|
||||
GLSMBuffers.glBufferData(target, data, usage);
|
||||
GLSMBuffers.glBindBuffer(target, 0);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -145,49 +147,38 @@ public class DSAUnsupported implements DSAAccess {
|
||||
@Override
|
||||
public void blitFramebuffer(int source, int dest, int offsetX, int offsetY, int width, int height, int offsetX2, int offsetY2, int width2, int height2,
|
||||
int bufferChoice, int filter) {
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, source);
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, dest);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, source);
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, dest);
|
||||
RENDER_BACKEND.blitFramebuffer(offsetX, offsetY, width, height, offsetX2, offsetY2, width2, height2, bufferChoice, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void framebufferTexture2D(int fb, int fbtarget, int attachment, int target, int texture, int levels) {
|
||||
GLStateManager.glBindFramebuffer(fbtarget, fb);
|
||||
RENDER_BACKEND.framebufferTexture2D(fbtarget, attachment, target, texture, levels);
|
||||
GLSMFramebuffer.glBindFramebuffer(fbtarget, fb);
|
||||
GLSMFramebuffer.glFramebufferTexture2D(fbtarget, attachment, target, texture, levels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int createFramebuffer() {
|
||||
final int framebuffer = GLStateManager.glGenFramebuffers();
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_FRAMEBUFFER, framebuffer);
|
||||
final int framebuffer = GLSMFramebuffer.glGenFramebuffers();
|
||||
GLSMFramebuffer.glBindFramebuffer(GL30.GL_FRAMEBUFFER, framebuffer);
|
||||
return framebuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int createTexture(int target) {
|
||||
final int texture = GLStateManager.glGenTextures();
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
final int texture = GLSMTextures.glGenTextures();
|
||||
GLSMTextures.glBindTexture(target, texture);
|
||||
return texture;
|
||||
}
|
||||
|
||||
private static int bindingQuery(int target) {
|
||||
return switch (target) {
|
||||
case GL11.GL_TEXTURE_1D -> GL11.GL_TEXTURE_BINDING_1D;
|
||||
case GL12.GL_TEXTURE_3D -> GL12.GL_TEXTURE_BINDING_3D;
|
||||
case GL13.GL_TEXTURE_CUBE_MAP -> GL13.GL_TEXTURE_BINDING_CUBE_MAP;
|
||||
case GL30.GL_TEXTURE_2D_ARRAY -> GL30.GL_TEXTURE_BINDING_2D_ARRAY;
|
||||
case GL31.GL_TEXTURE_RECTANGLE -> GL31.GL_TEXTURE_BINDING_RECTANGLE;
|
||||
default -> GL11.GL_TEXTURE_BINDING_2D;
|
||||
};
|
||||
}
|
||||
|
||||
private static int previousBinding(int target) {
|
||||
return target == GL11.GL_TEXTURE_2D ? previous2D() : RENDER_BACKEND.getInteger(bindingQuery(target));
|
||||
return target == GL11.GL_TEXTURE_2D ? previous2D() : RENDER_BACKEND.getInteger(TextureTargets.bindingQuery(target));
|
||||
}
|
||||
|
||||
private static int previous2D() {
|
||||
if (GLStateManager.isCachingEnabled()) {
|
||||
final TextureBindingStack slot = GLStateManager.getTextures().getTextureUnitBindings(GLStateManager.getActiveTextureUnit());
|
||||
final TextureBindingStack slot = GLSMTextures.getTextures().getTextureUnitBindings(GLSMTextures.getActiveTextureUnit());
|
||||
final int t = slot.getTarget();
|
||||
if (t == 0 || t == GL11.GL_TEXTURE_2D) return slot.getBinding();
|
||||
}
|
||||
@@ -196,13 +187,13 @@ public class DSAUnsupported implements DSAAccess {
|
||||
|
||||
private static int bindForEdit(int target, int texture) {
|
||||
final int previous = previousBinding(target);
|
||||
if (target == GL11.GL_TEXTURE_2D) GLStateManager.glBindTexture(target, texture);
|
||||
if (target == GL11.GL_TEXTURE_2D) GLSMTextures.glBindTexture(target, texture);
|
||||
else RENDER_BACKEND.bindTexture(target, texture);
|
||||
return previous;
|
||||
}
|
||||
|
||||
private static void restoreBinding(int target, int previous) {
|
||||
if (target == GL11.GL_TEXTURE_2D) GLStateManager.glBindTexture(target, previous);
|
||||
if (target == GL11.GL_TEXTURE_2D) GLSMTextures.glBindTexture(target, previous);
|
||||
else RENDER_BACKEND.bindTexture(target, previous);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
public final class ClipDistanceGlsl {
|
||||
|
||||
public static final String VS_OUT_DIST0 = "out vec4 angelica_ClipDist0;";
|
||||
public static final String VS_OUT_DIST1 = "out vec4 angelica_ClipDist1;";
|
||||
public static final String FS_IN_DIST0 = "in vec4 angelica_ClipDist0;";
|
||||
public static final String FS_IN_DIST1 = "in vec4 angelica_ClipDist1;";
|
||||
public static final String FS_DISCARD = "if (any(lessThan(angelica_ClipDist0, vec4(0.0))) || any(lessThan(angelica_ClipDist1, vec4(0.0)))) discard;\n";
|
||||
|
||||
private ClipDistanceGlsl() {}
|
||||
|
||||
public static void appendVsAssign(StringBuilder sb, String[] distances) {
|
||||
sb.append(" angelica_ClipDist0 = vec4(").append(distances[0]).append(", ").append(distances[1]).append(", ").append(distances[2]).append(", ").append(distances[3]).append(");\n");
|
||||
sb.append(" angelica_ClipDist1 = vec4(").append(distances[4]).append(", ").append(distances[5]).append(", ").append(distances[6]).append(", ").append(distances[7]).append(");\n");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBlend;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMEnable;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMLighting;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMMatrices;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMPrograms;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMTextures;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -24,14 +30,14 @@ public final class CombinedGlint {
|
||||
}
|
||||
|
||||
public static boolean begin(Matrix4fc secondTextureMatrix) {
|
||||
if (active || GLStateManager.getActiveProgram() != 0 || GLStateManager.getLightingState().isEnabled() || GLStateManager.getColorSumState().isEnabled() || !GLStateManager.glIsEnabled(GL11.GL_BLEND)) return false;
|
||||
final var blend = GLStateManager.getBlendState();
|
||||
if (active || GLSMPrograms.getActiveProgram() != 0 || GLSMLighting.getLightingState().isEnabled() || GLSMCurrentAttribs.getColorSumState().isEnabled() || !GLSMEnable.glIsEnabled(GL11.GL_BLEND)) return false;
|
||||
final var blend = GLSMBlend.getBlendState();
|
||||
final boolean lastAlpha = blend.getSrcAlpha() == GL11.GL_ONE && blend.getDstAlpha() == GL11.GL_ZERO && blend.getEquationAlpha() == GL14.GL_FUNC_ADD;
|
||||
final boolean preserveAlpha = blend.getSrcAlpha() == GL11.GL_ZERO && blend.getDstAlpha() == GL11.GL_ONE && (blend.getEquationAlpha() == GL14.GL_FUNC_ADD || blend.getEquationAlpha() == GL14.GL_FUNC_REVERSE_SUBTRACT);
|
||||
if (blend.getSrcRgb() != GL11.GL_SRC_COLOR || blend.getDstRgb() != GL11.GL_ONE
|
||||
|| (!lastAlpha && !preserveAlpha && (blend.getSrcAlpha() != GL11.GL_SRC_COLOR || blend.getDstAlpha() != GL11.GL_ONE || blend.getEquationAlpha() != blend.getEquationRgb()))
|
||||
|| (blend.getEquationRgb() != GL14.GL_FUNC_ADD && blend.getEquationRgb() != GL14.GL_FUNC_REVERSE_SUBTRACT)) return false;
|
||||
final var textures = GLStateManager.getTextures();
|
||||
final var textures = GLSMTextures.getTextures();
|
||||
if (!textures.getTextureUnitStates(0).isEnabled() || textures.getTextureUnitBindings(0).getBinding() == 0 || textures.getTexEnvState(0).mode != GL11.GL_MODULATE) return false;
|
||||
if (textures.getTextureUnitStates(1).isEnabled() && textures.getTextureUnitBindings(1).getBinding() != 0 && textures.getTexEnvState(1).mode != GL11.GL_MODULATE) return false;
|
||||
for (int unit = 2; unit < 4; unit++) {
|
||||
@@ -41,7 +47,7 @@ public final class CombinedGlint {
|
||||
relative.set(secondTextureMatrix).mul(inverse);
|
||||
if (!relative.isFinite()) return false;
|
||||
savedMatrix.set(textures.getTextureUnitMatrix(3));
|
||||
GLStateManager.setTextureMatrix(3, relative);
|
||||
GLSMMatrices.setTextureMatrix(3, relative);
|
||||
replaceAlpha = lastAlpha;
|
||||
active = true;
|
||||
return true;
|
||||
@@ -50,6 +56,6 @@ public final class CombinedGlint {
|
||||
public static void end() {
|
||||
if (!active) return;
|
||||
active = false;
|
||||
GLStateManager.setTextureMatrix(3, savedMatrix);
|
||||
GLSMMatrices.setTextureMatrix(3, savedMatrix);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public final class CubeInstancedAttribs {
|
||||
@@ -14,8 +14,8 @@ public final class CubeInstancedAttribs {
|
||||
|
||||
public static void pointInstanceAttribs(long base) {
|
||||
InstancedAttribs.pointHead(base, STRIDE);
|
||||
GLStateManager.glVertexAttribPointer(LOC_LIGHTMAP_SCALE, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_LIGHTMAP_SCALE);
|
||||
GLStateManager.glVertexAttribPointer(LOC_CUBE_TEX, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_CUBE_TEX);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_LIGHTMAP_SCALE, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_LIGHTMAP_SCALE);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_CUBE_TEX, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_CUBE_TEX);
|
||||
}
|
||||
|
||||
static void enableInstanceArrays() {
|
||||
|
||||
@@ -104,14 +104,17 @@ public final class FFPUniformBlock {
|
||||
public static final int TEX_ENV_COLOR_3 = vec4("u_TexEnvColor3");
|
||||
public static final int OVERLAY_COLOR = vec4("u_OverlayColor");
|
||||
public static final int SECONDARY_COLOR = vec3("u_SecondaryColor");
|
||||
public static final int ATLAS_GUTTER = flt("u_AtlasGutter");
|
||||
public static final int FOG_PARAMS = vec4("u_FogParams");
|
||||
public static final int FOG_COLOR = vec4("u_FogColor");
|
||||
|
||||
// Rain and snow, for Instancing.WEATHER. 0 = (translate.xyz, 1/radius),
|
||||
// 1 = (cameraFrac.xy, partialTicks, age), 2 = (rainScroll, snowScroll, rainStrength, unused).
|
||||
// Weather columns, for Instancing.WEATHER. 0 = (translate.xyz, 1/radius),
|
||||
// 1 = (cameraFrac.xy, partialTicks, age), 2 = (vanillaTick, providerTick, rainStrength, providerAge),
|
||||
// 3 = (provider 1/radius, unused, unused, unused).
|
||||
public static final int WEATHER_PARAMS_0 = vec4("u_WeatherParams0");
|
||||
public static final int WEATHER_PARAMS_1 = vec4("u_WeatherParams1");
|
||||
public static final int WEATHER_PARAMS_2 = vec4("u_WeatherParams2");
|
||||
public static final int WEATHER_PARAMS_3 = vec4("u_WeatherParams3");
|
||||
|
||||
public static final int SIZE;
|
||||
public static final String GLSL_DECL;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMLighting;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMMatrices;
|
||||
import com.gtnewhorizons.angelica.glsm.states.LightState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.MaterialState;
|
||||
import org.joml.Matrix3f;
|
||||
@@ -14,68 +16,145 @@ public final class FFPVertexLighting {
|
||||
private static final Vector4f scratchEyePos = new Vector4f();
|
||||
private static final Matrix3f scratchNormalMat = new Matrix3f();
|
||||
private static final Vector3f scratchVec = new Vector3f();
|
||||
private static final Vector3f scratchFactor = new Vector3f();
|
||||
private static final Vector3f base = new Vector3f();
|
||||
private static final Vector3f[] lightDirs = new Vector3f[VertexKey.FFP_LIGHT_COUNT];
|
||||
private static final Vector3f[] lightDiffuse = new Vector3f[VertexKey.FFP_LIGHT_COUNT];
|
||||
private static int litCount;
|
||||
private static boolean normalize;
|
||||
private static float rescale;
|
||||
|
||||
static {
|
||||
for (int i = 0; i < VertexKey.FFP_LIGHT_COUNT; i++) {
|
||||
lightDirs[i] = new Vector3f();
|
||||
lightDiffuse[i] = new Vector3f();
|
||||
}
|
||||
}
|
||||
|
||||
private FFPVertexLighting() {}
|
||||
|
||||
public static boolean modulatesVertexColor(Vector3f destFactor) {
|
||||
destFactor.set(1.0f);
|
||||
if (!prepare(false)) return false;
|
||||
|
||||
if (!GLStateManager.getLightingState().isEnabled()) return false;
|
||||
if (!GLStateManager.getColorMaterial().isEnabled()) return false;
|
||||
if (VertexKey.encodeColorMaterialMode(GLStateManager.getColorMaterialParameter().getValue()) != VertexKey.CM_AMBIENT_AND_DIFFUSE) return false;
|
||||
|
||||
final MaterialState material = GLStateManager.getFrontMaterial();
|
||||
if (material.emission.x != 0.0f || material.emission.y != 0.0f || material.emission.z != 0.0f)
|
||||
return false;
|
||||
|
||||
final boolean materialHasSpecular = material.shininess > 0.0f && (material.specular.x != 0.0f || material.specular.y != 0.0f || material.specular.z != 0.0f);
|
||||
|
||||
final Vector4f lightModelAmbient = GLStateManager.getLightModel().ambient;
|
||||
float r = lightModelAmbient.x;
|
||||
float g = lightModelAmbient.y;
|
||||
float b = lightModelAmbient.z;
|
||||
|
||||
final var lightEnables = GLStateManager.getLightStates();
|
||||
final var lightData = GLStateManager.getLightDataStates();
|
||||
boolean normalReady = false;
|
||||
|
||||
for (int i = 0; i < VertexKey.FFP_LIGHT_COUNT; i++) {
|
||||
if (!lightEnables[i].isEnabled()) continue;
|
||||
final LightState light = lightData[i];
|
||||
if (materialHasSpecular && (light.specular.x != 0.0f || light.specular.y != 0.0f || light.specular.z != 0.0f))
|
||||
return false;
|
||||
if (!normalReady) {
|
||||
transformCurrentNormal();
|
||||
normalReady = true;
|
||||
}
|
||||
final float nDotVP = Math.max(scratchNormal.dot(lightDirection(light)), 0.0f);
|
||||
r += light.ambient.x + nDotVP * light.diffuse.x;
|
||||
g += light.ambient.y + nDotVP * light.diffuse.y;
|
||||
b += light.ambient.z + nDotVP * light.diffuse.z;
|
||||
}
|
||||
|
||||
factor(ShaderManager.getCurrentNormal(), scratchFactor);
|
||||
final float r = scratchFactor.x;
|
||||
final float g = scratchFactor.y;
|
||||
final float b = scratchFactor.z;
|
||||
if (r == 1.0f && g == 1.0f && b == 1.0f) return false;
|
||||
if (!Float.isFinite(r + g + b)) return false;
|
||||
destFactor.set(r, g, b);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void transformCurrentNormal() {
|
||||
GLStateManager.getModelViewMatrix().normal(scratchNormalMat);
|
||||
scratchNormal.set(ShaderManager.getCurrentNormal());
|
||||
scratchNormalMat.transform(scratchNormal);
|
||||
if (GLStateManager.getNormalizeState().isEnabled()) {
|
||||
scratchNormal.normalize();
|
||||
} else if (GLStateManager.getRescaleNormalState().isEnabled()) {
|
||||
scratchNormal.mul(Uniforms.rescaleFactor(scratchNormalMat, scratchVec));
|
||||
public static boolean bakeColors(int[] rawBuffer, int vertexCount, boolean hasNormals, boolean hasColor) {
|
||||
if (vertexCount <= 0 || !prepare(true)) return false;
|
||||
|
||||
if (!hasNormals) factor(ShaderManager.getCurrentNormal(), scratchFactor);
|
||||
float cr = 0.0f, cg = 0.0f, cb = 0.0f;
|
||||
int alphaBits = 0;
|
||||
if (!hasColor) {
|
||||
final var color = GLSMCurrentAttribs.getColor();
|
||||
cr = clamp01(color.getRed());
|
||||
cg = clamp01(color.getGreen());
|
||||
cb = clamp01(color.getBlue());
|
||||
alphaBits = toByte(clamp01(color.getAlpha())) << 24;
|
||||
}
|
||||
|
||||
boolean haveNormal = false;
|
||||
int lastNormal = 0;
|
||||
for (int v = 0, i = 0; v < vertexCount; v++, i += 8) {
|
||||
if (hasNormals) {
|
||||
final int packed = rawBuffer[i + 6];
|
||||
if (!haveNormal || packed != lastNormal) {
|
||||
factor((byte) packed / 127.0f, (byte) (packed >> 8) / 127.0f, (byte) (packed >> 16) / 127.0f, scratchFactor);
|
||||
lastNormal = packed;
|
||||
haveNormal = true;
|
||||
}
|
||||
}
|
||||
if (hasColor) {
|
||||
final int packed = rawBuffer[i + 5];
|
||||
cr = (packed & 0xFF) / 255.0f;
|
||||
cg = ((packed >>> 8) & 0xFF) / 255.0f;
|
||||
cb = ((packed >>> 16) & 0xFF) / 255.0f;
|
||||
alphaBits = packed & 0xFF000000;
|
||||
}
|
||||
rawBuffer[i + 5] = alphaBits | (toByte(clamp01(cb * scratchFactor.z)) << 16) | (toByte(clamp01(cg * scratchFactor.y)) << 8) | toByte(clamp01(cr * scratchFactor.x));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean prepare(boolean directionalOnly) {
|
||||
if (!GLSMLighting.getLightingState().isEnabled()) return false;
|
||||
if (!GLSMLighting.getColorMaterial().isEnabled()) return false;
|
||||
if (VertexKey.encodeColorMaterialMode(GLSMLighting.getColorMaterialParameter().getValue()) != VertexKey.CM_AMBIENT_AND_DIFFUSE) return false;
|
||||
|
||||
final MaterialState material = GLSMLighting.getFrontMaterial();
|
||||
if (material.emission.x != 0.0f || material.emission.y != 0.0f || material.emission.z != 0.0f)
|
||||
return false;
|
||||
|
||||
final boolean materialHasSpecular = material.shininess > 0.0f && (material.specular.x != 0.0f || material.specular.y != 0.0f || material.specular.z != 0.0f);
|
||||
|
||||
final Vector4f lightModelAmbient = GLSMLighting.getLightModel().ambient;
|
||||
base.set(lightModelAmbient.x, lightModelAmbient.y, lightModelAmbient.z);
|
||||
|
||||
final var lightEnables = GLSMLighting.getLightStates();
|
||||
final var lightData = GLSMLighting.getLightDataStates();
|
||||
litCount = 0;
|
||||
|
||||
for (int i = 0; i < VertexKey.FFP_LIGHT_COUNT; i++) {
|
||||
if (!lightEnables[i].isEnabled()) continue;
|
||||
final LightState light = lightData[i];
|
||||
if (materialHasSpecular && (light.specular.x != 0.0f || light.specular.y != 0.0f || light.specular.z != 0.0f))
|
||||
return false;
|
||||
if (directionalOnly && light.position.w != 0.0f) return false;
|
||||
base.add(light.ambient.x, light.ambient.y, light.ambient.z);
|
||||
lightDirs[litCount].set(lightDirection(light));
|
||||
lightDiffuse[litCount].set(light.diffuse.x, light.diffuse.y, light.diffuse.z);
|
||||
litCount++;
|
||||
}
|
||||
|
||||
if (litCount > 0) {
|
||||
GLSMMatrices.getModelViewMatrix().normal(scratchNormalMat);
|
||||
normalize = GLSMLighting.getNormalizeState().isEnabled();
|
||||
rescale = !normalize && GLSMLighting.getRescaleNormalState().isEnabled() ? Uniforms.rescaleFactor(scratchNormalMat, scratchVec) : 1.0f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void factor(Vector3f normal, Vector3f dest) {
|
||||
factor(normal.x, normal.y, normal.z, dest);
|
||||
}
|
||||
|
||||
private static void factor(float nx, float ny, float nz, Vector3f dest) {
|
||||
dest.set(base);
|
||||
if (litCount == 0) return;
|
||||
scratchNormal.set(nx, ny, nz);
|
||||
scratchNormalMat.transform(scratchNormal);
|
||||
if (normalize) {
|
||||
scratchNormal.normalize();
|
||||
} else {
|
||||
scratchNormal.mul(rescale);
|
||||
}
|
||||
for (int i = 0; i < litCount; i++) {
|
||||
final float nDotVP = Math.max(scratchNormal.dot(lightDirs[i]), 0.0f);
|
||||
dest.fma(nDotVP, lightDiffuse[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static float clamp01(float value) {
|
||||
return Math.min(Math.max(value, 0.0f), 1.0f);
|
||||
}
|
||||
|
||||
private static int toByte(float unit) {
|
||||
return (int) (unit * 255.0f + 0.5f);
|
||||
}
|
||||
|
||||
private static Vector3f lightDirection(LightState light) {
|
||||
if (light.position.w == 0.0f) {
|
||||
scratchLightVec.set(light.position.x, light.position.y, light.position.z);
|
||||
} else {
|
||||
scratchEyePos.set(0.0f, 0.0f, 0.0f, 1.0f).mul(GLStateManager.getModelViewMatrix());
|
||||
scratchEyePos.set(0.0f, 0.0f, 0.0f, 1.0f).mul(GLSMMatrices.getModelViewMatrix());
|
||||
scratchLightVec.set(light.position.x - scratchEyePos.x, light.position.y - scratchEyePos.y, light.position.z - scratchEyePos.z);
|
||||
}
|
||||
return scratchLightVec.normalize();
|
||||
|
||||
@@ -3,6 +3,9 @@ package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.cel.api.util.NormI8;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.BatchStateGuard;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
@@ -213,24 +216,24 @@ public final class FfpExtendedAttribs {
|
||||
final int extVbo = getOrBuild(h, pos, uv, normal, first, count, extPrim, mode);
|
||||
if (extVbo == 0) return false;
|
||||
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, extVbo);
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, extVbo);
|
||||
ImmediateExtendedAttribHandler.setupExtAttribPointers(0L, ImmediateExtendedAttribHandler.EXT_STRIDE);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void unbind() {
|
||||
GLStateManager.glDisableVertexAttribArray(ImmediateExtendedAttribHandler.LOC_MID_TEX);
|
||||
GLStateManager.glDisableVertexAttribArray(ImmediateExtendedAttribHandler.LOC_TANGENT);
|
||||
GLSMVertexInput.glDisableVertexAttribArray(ImmediateExtendedAttribHandler.LOC_MID_TEX);
|
||||
GLSMVertexInput.glDisableVertexAttribArray(ImmediateExtendedAttribHandler.LOC_TANGENT);
|
||||
setNeutralCurrentValues();
|
||||
}
|
||||
|
||||
public static void setNeutralCurrentValues() {
|
||||
BatchStateGuard.suspend();
|
||||
try {
|
||||
GLStateManager.glVertexAttrib2f(ImmediateExtendedAttribHandler.LOC_MID_TEX, 0.5f, 0.5f);
|
||||
GLStateManager.glVertexAttrib4f(ImmediateExtendedAttribHandler.LOC_TANGENT, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLSMCurrentAttribs.glVertexAttrib2f(ImmediateExtendedAttribHandler.LOC_MID_TEX, 0.5f, 0.5f);
|
||||
GLSMCurrentAttribs.glVertexAttrib4f(ImmediateExtendedAttribHandler.LOC_TANGENT, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
} finally {
|
||||
BatchStateGuard.resume();
|
||||
}
|
||||
@@ -372,22 +375,22 @@ public final class FfpExtendedAttribs {
|
||||
final int newCap = Math.min(MAX_EXT_VERTS, Math.max(neededVerts, buf.capacityVerts * 2));
|
||||
beginInternalGl();
|
||||
try {
|
||||
final int vbo = GLStateManager.glGenBuffers();
|
||||
final int vbo = GLSMBuffers.glGenBuffers();
|
||||
if (vbo == 0) return false;
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glBufferData(GL15.GL_ARRAY_BUFFER, (long) newCap * extStride, GL15.GL_STATIC_DRAW);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLSMBuffers.glBufferData(GL15.GL_ARRAY_BUFFER, (long) newCap * extStride, GL15.GL_STATIC_DRAW);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
if (buf.vbo != 0) {
|
||||
final int savedRead = GLStateManager.getBoundCopyReadBuffer();
|
||||
final int savedWrite = GLStateManager.getBoundCopyWriteBuffer();
|
||||
GLStateManager.glBindBuffer(GL31.GL_COPY_READ_BUFFER, buf.vbo);
|
||||
GLStateManager.glBindBuffer(GL31.GL_COPY_WRITE_BUFFER, vbo);
|
||||
GLStateManager.glCopyBufferSubData(GL31.GL_COPY_READ_BUFFER, GL31.GL_COPY_WRITE_BUFFER, 0L, 0L,
|
||||
final int savedRead = GLSMBuffers.getBoundCopyReadBuffer();
|
||||
final int savedWrite = GLSMBuffers.getBoundCopyWriteBuffer();
|
||||
GLSMBuffers.glBindBuffer(GL31.GL_COPY_READ_BUFFER, buf.vbo);
|
||||
GLSMBuffers.glBindBuffer(GL31.GL_COPY_WRITE_BUFFER, vbo);
|
||||
GLSMBuffers.glCopyBufferSubData(GL31.GL_COPY_READ_BUFFER, GL31.GL_COPY_WRITE_BUFFER, 0L, 0L,
|
||||
(long) buf.capacityVerts * extStride);
|
||||
GLStateManager.glBindBuffer(GL31.GL_COPY_READ_BUFFER, savedRead);
|
||||
GLStateManager.glBindBuffer(GL31.GL_COPY_WRITE_BUFFER, savedWrite);
|
||||
GLStateManager.glDeleteBuffers(buf.vbo);
|
||||
GLSMBuffers.glBindBuffer(GL31.GL_COPY_READ_BUFFER, savedRead);
|
||||
GLSMBuffers.glBindBuffer(GL31.GL_COPY_WRITE_BUFFER, savedWrite);
|
||||
GLSMBuffers.glDeleteBuffers(buf.vbo);
|
||||
}
|
||||
buf.vbo = vbo;
|
||||
buf.capacityVerts = newCap;
|
||||
@@ -433,11 +436,11 @@ public final class FfpExtendedAttribs {
|
||||
|
||||
beginInternalGl();
|
||||
try {
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, extVbo);
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, extVbo);
|
||||
ext.position(0).limit(count * extStride);
|
||||
GLStateManager.glBufferSubData(GL15.GL_ARRAY_BUFFER, (long) first * extStride, ext);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
GLSMBuffers.glBufferSubData(GL15.GL_ARRAY_BUFFER, (long) first * extStride, ext);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
} finally {
|
||||
endInternalGl();
|
||||
}
|
||||
@@ -454,10 +457,10 @@ public final class FfpExtendedAttribs {
|
||||
final int bytes = (count - 1) * stride + elementBytes;
|
||||
final ByteBuffer dst = memAlloc(bytes).order(ByteOrder.nativeOrder());
|
||||
dst.position(0).limit(bytes);
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, a.vboId);
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, a.vboId);
|
||||
RENDER_BACKEND.getBufferSubData(GL15.GL_ARRAY_BUFFER, a.offset + (long) first * stride, dst);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
dst.position(0).limit(bytes);
|
||||
return dst;
|
||||
}
|
||||
@@ -484,7 +487,7 @@ public final class FfpExtendedAttribs {
|
||||
beginInternalGl();
|
||||
try {
|
||||
for (int i = 0; i < vbos.size(); i++) {
|
||||
GLStateManager.glDeleteBuffers(vbos.getInt(i));
|
||||
GLSMBuffers.glDeleteBuffers(vbos.getInt(i));
|
||||
}
|
||||
} finally {
|
||||
endInternalGl();
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.states.FogState;
|
||||
|
||||
public final class FfpGlsl {
|
||||
|
||||
private FfpGlsl() {}
|
||||
|
||||
// Mesa ffvertex_prog.c build_fog(): FDM_EYE_RADIAL/EYE_PLANE/EYE_PLANE_ABS
|
||||
public static String fogDistance(int mode, String eye) {
|
||||
return switch (mode) {
|
||||
case FogState.DISTANCE_EYE_RADIAL -> "length(" + eye + ".xyz)";
|
||||
case FogState.DISTANCE_EYE_PLANE -> eye + ".z";
|
||||
default -> "abs(" + eye + ".z)";
|
||||
};
|
||||
}
|
||||
|
||||
public static void appendFogFactor(StringBuilder sb, String indent, int fogMode, String coord, String params) {
|
||||
switch (fogMode) {
|
||||
case FragmentKey.FOG_LINEAR -> sb.append(indent).append("f = ").append(coord).append(" * ").append(params).append(".x + ").append(params).append(".y;\n");
|
||||
case FragmentKey.FOG_EXP -> sb.append(indent).append("f = exp2(-(").append(coord).append(" * ").append(params).append(".z));\n");
|
||||
case FragmentKey.FOG_EXP2 -> {
|
||||
sb.append(indent).append("float fogTmp = ").append(coord).append(" * ").append(params).append(".w;\n");
|
||||
sb.append(indent).append("f = exp2(-(fogTmp * fogTmp));\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String quantizeAlpha(String alpha) {
|
||||
return "round(" + alpha + " * 255.0)";
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,11 @@ package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMRasterizer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TexEnvState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
@@ -65,14 +67,25 @@ public final class FragmentKey {
|
||||
public static final int FOG_EXP = 2;
|
||||
public static final int FOG_EXP2 = 3;
|
||||
|
||||
public static int activeFogMode(GLContextState glCtx) {
|
||||
if (!glCtx.fogMode.isEnabled()) return FOG_NONE;
|
||||
return switch (glCtx.fogState.getFogMode()) {
|
||||
case GL11.GL_LINEAR -> FOG_LINEAR;
|
||||
case GL11.GL_EXP -> FOG_EXP;
|
||||
case GL11.GL_EXP2 -> FOG_EXP2;
|
||||
default -> FOG_NONE;
|
||||
};
|
||||
}
|
||||
|
||||
private static final int GLOBAL_BITS = 14;
|
||||
private static final int BIT_COMBINED_GLINT = 61;
|
||||
private static final int BIT_GLINT_REPLACE_ALPHA = 62;
|
||||
private static final int BIT_CLIP_DISCARD = 63;
|
||||
private static final int BIT_FOG_MODE = 0; // 2 bits
|
||||
private static final int BIT_ALPHA_TEST = 2; // 1 bit
|
||||
private static final int BIT_ALPHA_FUNC = 3; // 3 bits
|
||||
private static final int BIT_SEPARATE_SPECULAR = 6; // 1 bit
|
||||
private static final int BIT_NR_ENABLED_UNITS = 7; // 3 bits
|
||||
private static final int BIT_TEXTURE_SUPERSAMPLING = 7; // 3 bits, log2(samples)
|
||||
private static final int BIT_OVERLAY_ENABLED = 10; // 1 bit
|
||||
private static final int BIT_LINE_STIPPLE = 11; // 1 bit
|
||||
private static final int BIT_COLOR_SUM = 12; // 1 bit
|
||||
@@ -115,17 +128,10 @@ public final class FragmentKey {
|
||||
long global = 0;
|
||||
if (CombinedGlint.isActive()) global |= 1L << BIT_COMBINED_GLINT;
|
||||
if (CombinedGlint.replacesAlpha()) global |= 1L << BIT_GLINT_REPLACE_ALPHA;
|
||||
if (GLSMRasterizer.clipEmulationActive(glCtx)) global |= 1L << BIT_CLIP_DISCARD;
|
||||
|
||||
// Fog
|
||||
if (glCtx.fogMode.isEnabled()) {
|
||||
final int fogMode = switch (glCtx.fogState.getFogMode()) {
|
||||
case GL11.GL_LINEAR -> FOG_LINEAR;
|
||||
case GL11.GL_EXP -> FOG_EXP;
|
||||
case GL11.GL_EXP2 -> FOG_EXP2;
|
||||
default -> FOG_NONE;
|
||||
};
|
||||
global |= (long) fogMode;
|
||||
}
|
||||
global |= activeFogMode(glCtx);
|
||||
|
||||
// Alpha test
|
||||
if (glCtx.alphaTest.isEnabled()) {
|
||||
@@ -170,7 +176,10 @@ public final class FragmentKey {
|
||||
}
|
||||
|
||||
final int nrEnabled = highestEnabled + 1;
|
||||
global |= ((long) (nrEnabled & 0x7)) << BIT_NR_ENABLED_UNITS;
|
||||
if (glCtx.textureSupersamplingSamples > 1 && (unit0Bits & 1L) != 0
|
||||
&& TextureInfoCache.INSTANCE.getInfo(textures.getTextureUnitBindings(0).getBinding()).getAtlasGutter() > 0) {
|
||||
global |= (long) Integer.numberOfTrailingZeros(glCtx.textureSupersamplingSamples) << BIT_TEXTURE_SUPERSAMPLING;
|
||||
}
|
||||
global |= (unit0Bits << GLOBAL_BITS);
|
||||
out[0] = global;
|
||||
|
||||
@@ -253,13 +262,15 @@ public final class FragmentKey {
|
||||
|
||||
public int fogMode() { return (int) (packed[0] & 0x3); }
|
||||
public boolean combinedGlint() { return (packed[0] & (1L << BIT_COMBINED_GLINT)) != 0; }
|
||||
public boolean clipDiscard() { return (packed[0] & (1L << BIT_CLIP_DISCARD)) != 0; }
|
||||
public boolean glintReplaceAlpha() { return (packed[0] & (1L << BIT_GLINT_REPLACE_ALPHA)) != 0; }
|
||||
public int textureSupersamplingSamples() { return 1 << (int) ((packed[0] >> BIT_TEXTURE_SUPERSAMPLING) & 0x7); }
|
||||
public boolean alphaTestEnabled() { return ((packed[0] >> BIT_ALPHA_TEST) & 1) != 0; }
|
||||
public int alphaTestFunc() { return (int) ((packed[0] >> BIT_ALPHA_FUNC) & 0x7); }
|
||||
public boolean separateSpecular() { return ((packed[0] >> BIT_SEPARATE_SPECULAR) & 1) != 0; }
|
||||
public boolean colorSum() { return ((packed[0] >> BIT_COLOR_SUM) & 1) != 0; }
|
||||
public boolean lineStipple() { return ((packed[0] >> BIT_LINE_STIPPLE) & 1) != 0; }
|
||||
public int nrEnabledUnits() { return (int) ((packed[0] >> BIT_NR_ENABLED_UNITS) & 0x7); }
|
||||
public int nrEnabledUnits() { return packed.length == 1 && !unitEnabled(0) ? 0 : packed.length; }
|
||||
public boolean overlayEnabled() { return ((packed[0] >> BIT_OVERLAY_ENABLED) & 1) != 0; }
|
||||
public boolean overlayInstanced() { return ((packed[0] >> BIT_OVERLAY_INSTANCED) & 1) != 0; }
|
||||
|
||||
@@ -398,6 +409,7 @@ public final class FragmentKey {
|
||||
sb.append(String.format("FFPFragmentKey[fog=%s alpha=%b(%s) specSep=%b colorSum=%b overlay=%b units=%d", fogName, alphaTestEnabled(),
|
||||
alphaTestEnabled() ? String.format("0x%04X", decodeAlphaFunc(alphaTestFunc())) : "-", separateSpecular(), colorSum(),
|
||||
overlayEnabled() || overlayInstanced(), nrEnabledUnits()));
|
||||
if (textureSupersamplingSamples() > 1) sb.append(" samples=").append(textureSupersamplingSamples());
|
||||
for (int i = 0; i < nrEnabledUnits(); i++) {
|
||||
if (!unitEnabled(i)) {
|
||||
sb.append(String.format(" u%d=OFF", i));
|
||||
|
||||
+14
-14
@@ -28,8 +28,15 @@ public final class FragmentShaderGenerator {
|
||||
return sb.toString();
|
||||
}
|
||||
sb.append("out vec4 fragColor;\n\n");
|
||||
if (key.textureSupersamplingSamples() > 1) {
|
||||
sb.append("#define TEXTURE_SUPERSAMPLING_SAMPLES ").append(key.textureSupersamplingSamples()).append('\n');
|
||||
sb.append(ShaderLoader.getShaderSource("angelica:texture_supersampling.glsl"));
|
||||
}
|
||||
|
||||
sb.append("void main() {\n");
|
||||
if (key.clipDiscard()) {
|
||||
sb.append(ClipDistanceGlsl.FS_DISCARD);
|
||||
}
|
||||
emitLineStipple(sb, key);
|
||||
emitTextureSampling(sb, key);
|
||||
emitTexEnvChain(sb, key);
|
||||
@@ -45,6 +52,9 @@ public final class FragmentShaderGenerator {
|
||||
private static void emitInputs(StringBuilder sb, FragmentKey key) {
|
||||
sb.append("// Inputs from vertex shader\n");
|
||||
sb.append("in vec4 v_Color;\n");
|
||||
if (key.clipDiscard()) {
|
||||
sb.append(ClipDistanceGlsl.FS_IN_DIST0).append('\n').append(ClipDistanceGlsl.FS_IN_DIST1).append('\n');
|
||||
}
|
||||
if (key.overlayInstanced()) {
|
||||
sb.append("in vec4 v_Overlay;\n");
|
||||
}
|
||||
@@ -86,7 +96,8 @@ public final class FragmentShaderGenerator {
|
||||
private static void emitTextureSampling(StringBuilder sb, FragmentKey key) {
|
||||
for (int i = 0; i < key.nrEnabledUnits(); i++) {
|
||||
if (!key.unitEnabled(i)) continue;
|
||||
sb.append(" vec4 tex").append(i).append("Color = textureProj(u_Sampler").append(i).append(", v_TexCoord").append(i).append(");\n");
|
||||
final String sample = i == 0 && key.textureSupersamplingSamples() > 1 ? "sampleSupersampledTexture" : "textureProj";
|
||||
sb.append(" vec4 tex").append(i).append("Color = ").append(sample).append("(u_Sampler").append(i).append(", v_TexCoord").append(i).append(");\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +316,7 @@ public final class FragmentShaderGenerator {
|
||||
final int func = FragmentKey.decodeAlphaFunc(key.alphaTestFunc());
|
||||
|
||||
|
||||
sb.append(" float qa = round(color.a * 255.0);\n");
|
||||
sb.append(" float qa = ").append(FfpGlsl.quantizeAlpha("color.a")).append(";\n");
|
||||
switch (func) {
|
||||
case GL11.GL_NEVER ->
|
||||
sb.append(" discard;\n");
|
||||
@@ -335,18 +346,7 @@ public final class FragmentShaderGenerator {
|
||||
|
||||
sb.append(" // Fog\n");
|
||||
sb.append(" float f;\n");
|
||||
|
||||
switch (fogMode) {
|
||||
case FragmentKey.FOG_LINEAR ->
|
||||
sb.append(" f = v_FogCoord * u_FogParams.x + u_FogParams.y;\n");
|
||||
case FragmentKey.FOG_EXP ->
|
||||
sb.append(" f = exp2(-(v_FogCoord * u_FogParams.z));\n");
|
||||
case FragmentKey.FOG_EXP2 -> {
|
||||
sb.append(" float fogTmp = v_FogCoord * u_FogParams.w;\n");
|
||||
sb.append(" f = exp2(-(fogTmp * fogTmp));\n");
|
||||
}
|
||||
}
|
||||
|
||||
FfpGlsl.appendFogFactor(sb, " ", fogMode, "v_FogCoord", "u_FogParams");
|
||||
sb.append(" f = clamp(f, 0.0, 1.0);\n");
|
||||
sb.append(" color.rgb = mix(u_FogColor.rgb, color.rgb, f);\n");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memPutFloat;
|
||||
@@ -68,20 +68,20 @@ public final class InstancedAttribs {
|
||||
|
||||
public static void pointHead(long base, int stride) {
|
||||
for (int r = 0; r < 3; r++) {
|
||||
GLStateManager.glVertexAttribPointer(LOC_ROW0 + r, 4, GL11.GL_FLOAT, false, stride, base + OFFSET_ROWS + r * 16L);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_ROW0 + r, 4, GL11.GL_FLOAT, false, stride, base + OFFSET_ROWS + r * 16L);
|
||||
}
|
||||
GLStateManager.glVertexAttribPointer(LOC_COLOR, 4, GL11.GL_UNSIGNED_BYTE, true, stride, base + OFFSET_COLOR);
|
||||
GLStateManager.glVertexAttribPointer(LOC_OVERLAY, 4, GL11.GL_UNSIGNED_BYTE, true, stride, base + OFFSET_OVERLAY);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_COLOR, 4, GL11.GL_UNSIGNED_BYTE, true, stride, base + OFFSET_COLOR);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_OVERLAY, 4, GL11.GL_UNSIGNED_BYTE, true, stride, base + OFFSET_OVERLAY);
|
||||
pointEntityIds(LOC_ENTITY, stride, base + OFFSET_ENTITY);
|
||||
}
|
||||
|
||||
public static void pointEntityIds(int location, int stride, long offset) {
|
||||
GLStateManager.glVertexAttribPointer(location, 4, GL11.GL_UNSIGNED_SHORT, true, stride, offset);
|
||||
GLSMVertexInput.glVertexAttribPointer(location, 4, GL11.GL_UNSIGNED_SHORT, true, stride, offset);
|
||||
}
|
||||
|
||||
public static void pointTemplate(long base) {
|
||||
pointHead(base, STRIDE);
|
||||
GLStateManager.glVertexAttribPointer(LOC_LIGHTMAP, 2, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_LIGHTMAP);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_LIGHTMAP, 2, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_LIGHTMAP);
|
||||
}
|
||||
|
||||
public static void enableHeadArrays() {
|
||||
@@ -91,8 +91,8 @@ public final class InstancedAttribs {
|
||||
}
|
||||
|
||||
static void enableInstanced(int loc) {
|
||||
GLStateManager.glEnableVertexAttribArray(loc);
|
||||
GLStateManager.glVertexAttribDivisor(loc, 1);
|
||||
GLSMVertexInput.glEnableVertexAttribArray(loc);
|
||||
GLSMVertexInput.glVertexAttribDivisor(loc, 1);
|
||||
}
|
||||
|
||||
private InstancedAttribs() {}
|
||||
|
||||
@@ -39,17 +39,16 @@ public final class InstancedGlslHelpers {
|
||||
vec2 {p}wColumn = {span}.xy;
|
||||
float {p}wBottom = {span}.z;
|
||||
float {p}wTop = {span}.w;
|
||||
vec2 {p}wLightmap = {params}.xy;
|
||||
float {p}wHash = {params}.z;
|
||||
bool {p}wSnow = {params}.w > 0.5;
|
||||
float {p}wLightV = floor({params}.x / 65536.0);
|
||||
vec2 {p}wLightmap = vec2({params}.x - {p}wLightV * 65536.0, {p}wLightV);
|
||||
bool {p}wProvider = {params}.w > 0.5;
|
||||
vec3 {p}wTranslate = {p}WeatherParams0.xyz;
|
||||
float {p}wInvRadius = {p}WeatherParams0.w;
|
||||
float {p}wInvRadius = {p}wProvider ? {p}WeatherParams3.x : {p}WeatherParams0.w;
|
||||
vec2 {p}wCameraFrac = {p}WeatherParams1.xy;
|
||||
float {p}wPartialTicks = {p}WeatherParams1.z;
|
||||
float {p}wAge = {p}WeatherParams1.w;
|
||||
float {p}wRainScroll = {p}WeatherParams2.x;
|
||||
float {p}wSnowScroll = {p}WeatherParams2.y;
|
||||
float {p}wStrength = {p}WeatherParams2.z;
|
||||
float {p}wAge = {p}wProvider ? {p}WeatherParams2.w : {p}WeatherParams1.w;
|
||||
float {p}wTick = {p}wProvider ? {p}WeatherParams2.y : {p}WeatherParams2.x;
|
||||
float {p}wStrength = {p}wProvider ? 1.0 : {p}WeatherParams2.z;
|
||||
|
||||
vec2 {p}wHalfWidth = vec2(-{p}wColumn.y, {p}wColumn.x) * (0.5 / sqrt(dot({p}wColumn, {p}wColumn)));
|
||||
vec2 {p}wCornerXZ = {p}wColumn + vec2(0.5) + ({corner}.x * 2.0 - 1.0) * {p}wHalfWidth;
|
||||
@@ -58,22 +57,13 @@ public final class InstancedGlslHelpers {
|
||||
|
||||
float {p}wDistance = length({p}wColumn + vec2(0.5) - {p}wCameraFrac) * {p}wInvRadius;
|
||||
float {p}wFade = 1.0 - {p}wDistance * {p}wDistance;
|
||||
float {p}wScroll;
|
||||
vec2 {p}wDrift;
|
||||
float {p}wAlpha;
|
||||
if ({p}wSnow) {
|
||||
{p}wScroll = ({p}wSnowScroll + {p}wPartialTicks) / 512.0;
|
||||
{p}wDrift = vec2({jitter}.x + {p}wAge * 0.01 * {jitter}.y, {jitter}.z + {p}wAge * {jitter}.w * 0.001);
|
||||
{p}wAlpha = {p}wFade * 0.3 + 0.5;
|
||||
} else {
|
||||
{p}wScroll = (mod({p}wRainScroll + {p}wHash, 32.0) + {p}wPartialTicks) / 32.0 * (3.0 + {jitter}.x);
|
||||
{p}wDrift = vec2(0.0);
|
||||
{p}wAlpha = {p}wFade * 0.5 + 0.5;
|
||||
}
|
||||
float {p}wScroll = (mod({p}wTick + {params}.y, {layer}.x) + {p}wPartialTicks) / {layer}.x * {params}.z;
|
||||
vec2 {p}wDrift = vec2({jitter}.x + {p}wAge * {layer}.y * {jitter}.y, {jitter}.z + {p}wAge * {layer}.z * {jitter}.w);
|
||||
float {p}wAlpha = {p}wFade * {layer}.w + 0.5;
|
||||
|
||||
{tex0} = vec4({corner}.x + {p}wDrift.x, {p}wCornerY * 0.25 + {p}wScroll + {p}wDrift.y, 0.0, 1.0);
|
||||
{tex1} = vec4({p}wLightmap, 0.0, 1.0);
|
||||
{color} = vec4(1.0, 1.0, 1.0, {p}wAlpha * {p}wStrength);""";
|
||||
{color} = floor(clamp(vec4({colorAttr}.rgb, {p}wAlpha * {colorAttr}.a * {p}wStrength), 0.0, 1.0) * 255.0) / 255.0;""";
|
||||
|
||||
public static String weatherPrologue(String uniformPrefix, String attribPrefix, String corner,
|
||||
String vertex, String color, String tex0, String tex1, String sep) {
|
||||
@@ -82,6 +72,8 @@ public final class InstancedGlslHelpers {
|
||||
.replace("{span}", attribPrefix + "InstColumnSpan")
|
||||
.replace("{jitter}", attribPrefix + "InstJitter")
|
||||
.replace("{params}", attribPrefix + "InstWeatherParams")
|
||||
.replace("{layer}", attribPrefix + "InstWeatherLayer")
|
||||
.replace("{colorAttr}", attribPrefix + "InstWeatherColor")
|
||||
.replace("{corner}", corner)
|
||||
.replace("{vertex}", vertex)
|
||||
.replace("{color}", color)
|
||||
@@ -125,6 +117,8 @@ public final class InstancedGlslHelpers {
|
||||
decls.add(decl(WeatherInstancedAttribs.LOC_COLUMN_SPAN, "vec4", prefix + "InstColumnSpan"));
|
||||
decls.add(decl(WeatherInstancedAttribs.LOC_JITTER, "vec4", prefix + "InstJitter"));
|
||||
decls.add(decl(WeatherInstancedAttribs.LOC_PARAMS, "vec4", prefix + "InstWeatherParams"));
|
||||
decls.add(decl(WeatherInstancedAttribs.LOC_COLOR, "vec4", prefix + "InstWeatherColor"));
|
||||
decls.add(decl(WeatherInstancedAttribs.LOC_LAYER, "vec4", prefix + "InstWeatherLayer"));
|
||||
}
|
||||
}
|
||||
return decls.toArray(String[]::new);
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memPutFloat;
|
||||
@@ -20,10 +20,10 @@ public final class ParticleInstancedAttribs {
|
||||
public static final int STRIDE = 48;
|
||||
|
||||
public static void pointInstanceAttribs(long base) {
|
||||
GLStateManager.glVertexAttribPointer(LOC_CENTER_HALF, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_CENTER_HALF);
|
||||
GLStateManager.glVertexAttribPointer(LOC_UV, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_UV);
|
||||
GLStateManager.glVertexAttribPointer(LOC_COLOR, 4, GL11.GL_UNSIGNED_BYTE, true, STRIDE, base + OFFSET_COLOR);
|
||||
GLStateManager.glVertexAttribPointer(LOC_LIGHTMAP, 2, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_LIGHTMAP);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_CENTER_HALF, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_CENTER_HALF);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_UV, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_UV);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_COLOR, 4, GL11.GL_UNSIGNED_BYTE, true, STRIDE, base + OFFSET_COLOR);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_LIGHTMAP, 2, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_LIGHTMAP);
|
||||
}
|
||||
|
||||
static void enableInstanceArrays() {
|
||||
|
||||
@@ -3,7 +3,8 @@ package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.cel.api.util.NormI8;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.ImmediateExtendedAttribHandler;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
@@ -76,11 +77,11 @@ public final class ParticleQuadMesh {
|
||||
written = true;
|
||||
|
||||
write(memAddress0(staging), rotX, rotXZ, rotZ, rotYZ, rotXY);
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
staging.position(0).limit(VERTEX_COUNT * VERTEX_STRIDE);
|
||||
GLStateManager.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0L, staging);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
GLSMBuffers.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0L, staging);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
}
|
||||
|
||||
private static void write(long dst, float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) {
|
||||
@@ -116,13 +117,13 @@ public final class ParticleQuadMesh {
|
||||
}
|
||||
|
||||
private static void build() {
|
||||
final int savedVAO = GLStateManager.getBoundVAO();
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
vao = GLStateManager.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
vbo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glBufferData(GL15.GL_ARRAY_BUFFER, (long) VERTEX_COUNT * VERTEX_STRIDE, GL15.GL_DYNAMIC_DRAW);
|
||||
final int savedVAO = GLSMVertexInput.getBoundVAO();
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
vao = GLSMVertexInput.glGenVertexArrays();
|
||||
GLSMVertexInput.glBindVertexArray(vao);
|
||||
vbo = GLSMBuffers.glGenBuffers();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLSMBuffers.glBufferData(GL15.GL_ARRAY_BUFFER, (long) VERTEX_COUNT * VERTEX_STRIDE, GL15.GL_DYNAMIC_DRAW);
|
||||
|
||||
attrib(VertexFormatElement.Usage.POSITION.getAttributeLocation(), 3, GL11.GL_FLOAT, false, OFFSET_OFFSET);
|
||||
attrib(VertexFormatElement.Usage.PRIMARY_UV.getAttributeLocation(), 2, GL11.GL_FLOAT, false, OFFSET_CORNER);
|
||||
@@ -130,25 +131,25 @@ public final class ParticleQuadMesh {
|
||||
|
||||
ParticleInstancedAttribs.enableInstanceArrays();
|
||||
|
||||
GLStateManager.glBindVertexArray(savedVAO);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
GLSMVertexInput.glBindVertexArray(savedVAO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
|
||||
if (staging == null) staging = memAlloc(VERTEX_COUNT * VERTEX_STRIDE);
|
||||
written = false;
|
||||
}
|
||||
|
||||
private static void attrib(int loc, int size, int type, boolean normalized, int offset) {
|
||||
GLStateManager.glEnableVertexAttribArray(loc);
|
||||
GLStateManager.glVertexAttribPointer(loc, size, type, normalized, VERTEX_STRIDE, offset);
|
||||
GLSMVertexInput.glEnableVertexAttribArray(loc);
|
||||
GLSMVertexInput.glVertexAttribPointer(loc, size, type, normalized, VERTEX_STRIDE, offset);
|
||||
}
|
||||
|
||||
public static void delete() {
|
||||
if (vbo != 0) {
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
GLSMBuffers.glDeleteBuffers(vbo);
|
||||
vbo = 0;
|
||||
}
|
||||
if (vao != 0) {
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
GLSMVertexInput.glDeleteVertexArrays(vao);
|
||||
vao = 0;
|
||||
}
|
||||
if (staging != null) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
import com.gtnewhorizons.angelica.config.SystemProperties;
|
||||
import com.gtnewhorizons.angelica.glsm.CompatShaderTransformer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLDebug;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMPrograms;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.RenderBackend;
|
||||
@@ -45,7 +46,7 @@ public class Program {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
GLStateManager.glDeleteProgram(programId);
|
||||
GLSMPrograms.glDeleteProgram(programId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +94,7 @@ public class Program {
|
||||
backend.uniformBlockBinding(program, blockIndex, FFPUniformBlock.BINDING_POINT);
|
||||
}
|
||||
|
||||
final int previousProgram = GLStateManager.getActiveProgram();
|
||||
final int previousProgram = GLSMPrograms.getActiveProgram();
|
||||
backend.useProgram(program);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (ffpProgram.locSampler[i] != -1) backend.uniform1i(ffpProgram.locSampler[i], i);
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizons.angelica.config.SystemProperties;
|
||||
import com.gtnewhorizons.angelica.glsm.CompatUniformManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.DeferredBlendHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
@@ -132,14 +133,14 @@ public final class ShaderManager {
|
||||
lastBoundProgramId = -1;
|
||||
currentVertexKeyPacked = Long.MIN_VALUE;
|
||||
currentFKLen = 0;
|
||||
GLStateManager.forceAttribDefaultsDirty();
|
||||
GLSMCurrentAttribs.forceAttribDefaultsDirty();
|
||||
}
|
||||
|
||||
public void preDraw(GLContextState glCtx) {
|
||||
GLSMHooks.resolvePendingProgram();
|
||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||
if (bh != null) bh.flushDeferredBlend();
|
||||
GLStateManager.flushEntityIds(glCtx);
|
||||
GLSMCurrentAttribs.flushEntityIds(glCtx);
|
||||
|
||||
// Handle FFP & Iris uniforms
|
||||
final int currentProgramId = glCtx.activeProgram;
|
||||
@@ -154,7 +155,7 @@ public final class ShaderManager {
|
||||
final boolean hasNormal = (vertexFlags & VertexFlags.NORMAL_BIT) != 0;
|
||||
final boolean hasTexCoord = (vertexFlags & VertexFlags.TEXTURE_BIT) != 0;
|
||||
final boolean hasLightmap = (vertexFlags & VertexFlags.BRIGHTNESS_BIT) != 0;
|
||||
GLStateManager.flushDeferredVertexAttribs(glCtx, hasColor, hasNormal, hasTexCoord, hasLightmap);
|
||||
GLSMCurrentAttribs.flushDeferredVertexAttribs(glCtx, hasColor, hasNormal, hasTexCoord, hasLightmap);
|
||||
|
||||
if (!active) return;
|
||||
|
||||
@@ -190,6 +191,10 @@ public final class ShaderManager {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTextureSupersampling() {
|
||||
return currentProgram != null && currentProgram.getFragmentKey().textureSupersamplingSamples() > 1;
|
||||
}
|
||||
|
||||
public static void endFrame() {
|
||||
final ShaderManager sm = GLStateManager.ctx().ffp;
|
||||
sm.lastFramePreDrawCalls = sm.preDrawCalls;
|
||||
@@ -199,18 +204,21 @@ public final class ShaderManager {
|
||||
}
|
||||
|
||||
public void setNormal(float x, float y, float z) {
|
||||
GLStateManager.recordExitNormal();
|
||||
normalStack.beforeModify();
|
||||
currentNormal.set(x, y, z);
|
||||
normalGeneration++;
|
||||
}
|
||||
|
||||
public void setTexCoord(float s, float t, float r, float q) {
|
||||
GLStateManager.recordExitTexCoord(0);
|
||||
texCoordStack.beforeModify();
|
||||
currentTexCoords[0].set(s, t, r, q);
|
||||
texCoordGeneration++;
|
||||
}
|
||||
|
||||
public void setTexCoord(int unit, float s, float t, float r, float q) {
|
||||
GLStateManager.recordExitTexCoord(unit);
|
||||
if (unit == 0) texCoordStack.beforeModify();
|
||||
currentTexCoords[unit].set(s, t, r, q);
|
||||
texCoordGeneration++;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ClipPlaneState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.FogState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.LightState;
|
||||
@@ -11,6 +11,7 @@ import com.gtnewhorizons.angelica.glsm.states.TexGenState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ViewportState;
|
||||
import com.gtnewhorizons.angelica.glsm.streaming.UniformRingBuffer;
|
||||
import com.gtnewhorizons.angelica.glsm.texture.TextureInfoCache;
|
||||
import org.joml.Math;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
@@ -49,6 +50,7 @@ public class Uniforms {
|
||||
private int viewportX = Integer.MIN_VALUE, viewportY = Integer.MIN_VALUE, viewportWidth = -1, viewportHeight = -1;
|
||||
private int lineStipple = -1;
|
||||
private int weatherGen = -1;
|
||||
private int atlasGutter = -1;
|
||||
|
||||
int blockWrites;
|
||||
int blockSkips;
|
||||
@@ -80,9 +82,6 @@ public class Uniforms {
|
||||
private final Vector3f tempVec3 = new Vector3f();
|
||||
private final FloatBuffer clipPlaneBuf = memAllocFloat(32); // 8 planes * vec4
|
||||
|
||||
private static final double LN2 = java.lang.Math.log(2.0);
|
||||
private static final double SQRT_LN2 = java.lang.Math.sqrt(LN2);
|
||||
|
||||
public void upload(GLContextState glCtx) {
|
||||
boolean dirty = false;
|
||||
contentChanged = false;
|
||||
@@ -173,6 +172,15 @@ public class Uniforms {
|
||||
stagedFragment++;
|
||||
dirty = true;
|
||||
}
|
||||
if (glCtx.textureSupersamplingSamples > 1 && ffp.isTextureSupersampling()) {
|
||||
final int gutter = TextureInfoCache.INSTANCE.getInfo(glCtx.textures.getTextureUnitBindings(0).getBinding()).getAtlasGutter();
|
||||
if (gutter != atlasGutter) {
|
||||
putFloat(FFPUniformBlock.ATLAS_GUTTER, gutter);
|
||||
atlasGutter = gutter;
|
||||
stagedMisc++;
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
final LineState line = glCtx.lineState;
|
||||
final float lw = line.getWidth();
|
||||
if (lw != lineWidth) {
|
||||
@@ -217,7 +225,7 @@ public class Uniforms {
|
||||
ring = new UniformRingBuffer(RING_CAPACITY, FFPUniformBlock.SIZE);
|
||||
}
|
||||
final int offset = ring.writeBlock(staging);
|
||||
GLStateManager.glBindBufferRange(GL31.GL_UNIFORM_BUFFER, FFPUniformBlock.BINDING_POINT,
|
||||
GLSMBuffers.glBindBufferRange(GL31.GL_UNIFORM_BUFFER, FFPUniformBlock.BINDING_POINT,
|
||||
ring.getBufferId(), offset, FFPUniformBlock.SIZE);
|
||||
bound = true;
|
||||
blockWrites++;
|
||||
@@ -233,8 +241,11 @@ public class Uniforms {
|
||||
if (projChanged) {
|
||||
putMat4(FFPUniformBlock.PROJECTION_MATRIX, proj);
|
||||
}
|
||||
proj.mul(mv, mvpMatrix);
|
||||
putMat4(FFPUniformBlock.MVP_MATRIX, mvpMatrix);
|
||||
putMat4(FFPUniformBlock.MVP_MATRIX, modelViewProjection(proj, mv, mvpMatrix));
|
||||
}
|
||||
|
||||
public static Matrix4f modelViewProjection(Matrix4f proj, Matrix4f mv, Matrix4f dest) {
|
||||
return proj.mul(mv, dest);
|
||||
}
|
||||
|
||||
private void stageNormalMatrix(GLContextState glCtx) {
|
||||
@@ -318,9 +329,7 @@ public class Uniforms {
|
||||
private void stageClipPlanes(GLContextState glCtx) {
|
||||
final ClipPlaneState cps = glCtx.clipPlaneState;
|
||||
clipPlaneBuf.clear();
|
||||
for (int i = 0; i < GLStateManager.MAX_CLIP_PLANES; i++) {
|
||||
cps.putEyePlane(i, clipPlaneBuf);
|
||||
}
|
||||
cps.putEffectivePlanes(glCtx.clipPlaneEnabledMask, clipPlaneBuf);
|
||||
final long src = memAddress0(clipPlaneBuf);
|
||||
for (int i = 0; i < 32 * 4; i += 4) {
|
||||
putInt(FFPUniformBlock.CLIP_PLANES + i, memGetInt(src + i));
|
||||
@@ -343,17 +352,8 @@ public class Uniforms {
|
||||
final var secondary = glCtx.secondaryColor;
|
||||
putVec3(FFPUniformBlock.SECONDARY_COLOR, secondary.getRed(), secondary.getGreen(), secondary.getBlue());
|
||||
|
||||
// Mesa STATE_FOG_PARAMS_OPTIMIZED
|
||||
final FogState fog = glCtx.fogState;
|
||||
final float start = fog.getStart();
|
||||
final float end = fog.getEnd();
|
||||
final float density = fog.getDensity();
|
||||
final float range = end - start;
|
||||
putVec4(FFPUniformBlock.FOG_PARAMS,
|
||||
range != 0.0f ? -1.0f / range : 0.0f,
|
||||
range != 0.0f ? end / range : 1.0f,
|
||||
(float) (density / LN2),
|
||||
(float) (density / SQRT_LN2));
|
||||
putVec4(FFPUniformBlock.FOG_PARAMS, fog.linearScale(), fog.linearBias(), fog.expScale(), fog.exp2Scale());
|
||||
putVec4(FFPUniformBlock.FOG_COLOR,
|
||||
(float) fog.getFogColor().x, (float) fog.getFogColor().y, (float) fog.getFogColor().z,
|
||||
fog.getFogAlpha());
|
||||
@@ -391,8 +391,9 @@ public class Uniforms {
|
||||
WeatherParams.translateZ, WeatherParams.invRadius);
|
||||
putVec4(FFPUniformBlock.WEATHER_PARAMS_1, WeatherParams.cameraFracX, WeatherParams.cameraFracZ,
|
||||
WeatherParams.partialTicks, WeatherParams.age);
|
||||
putVec4(FFPUniformBlock.WEATHER_PARAMS_2, WeatherParams.rainScroll, WeatherParams.snowScroll,
|
||||
WeatherParams.rainStrength, 0.0f);
|
||||
putVec4(FFPUniformBlock.WEATHER_PARAMS_2, WeatherParams.vanillaTick, WeatherParams.providerTick,
|
||||
WeatherParams.rainStrength, WeatherParams.providerAge);
|
||||
putVec4(FFPUniformBlock.WEATHER_PARAMS_3, WeatherParams.providerInvRadius, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
private void putVec4(int offset, Vector4f v) {
|
||||
@@ -420,6 +421,7 @@ public class Uniforms {
|
||||
if (ring != null) {
|
||||
ring.endFrame();
|
||||
}
|
||||
invalidateBinding();
|
||||
lastFrameBlockWrites = blockWrites;
|
||||
lastFrameBlockSkips = blockSkips;
|
||||
lastFrameStagedMatrices = stagedMatrices;
|
||||
|
||||
@@ -3,7 +3,8 @@ package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.cel.api.util.NormI8;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.ImmediateExtendedAttribHandler;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
@@ -113,19 +114,19 @@ public final class UnitCubeMesh {
|
||||
}
|
||||
|
||||
private static void build() {
|
||||
final int savedVAO = GLStateManager.getBoundVAO();
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
vao = GLStateManager.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
vbo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
final int savedVAO = GLSMVertexInput.getBoundVAO();
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
vao = GLSMVertexInput.glGenVertexArrays();
|
||||
GLSMVertexInput.glBindVertexArray(vao);
|
||||
vbo = GLSMBuffers.glGenBuffers();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
final int bytes = VERTEX_COUNT * VERTEX_STRIDE;
|
||||
final ByteBuffer data = memAlloc(bytes);
|
||||
try {
|
||||
write(memAddress0(data));
|
||||
data.position(0).limit(bytes);
|
||||
GLStateManager.glBufferData(GL15.GL_ARRAY_BUFFER, data, GL15.GL_STATIC_DRAW);
|
||||
GLSMBuffers.glBufferData(GL15.GL_ARRAY_BUFFER, data, GL15.GL_STATIC_DRAW);
|
||||
} finally {
|
||||
memFree(data);
|
||||
}
|
||||
@@ -139,22 +140,22 @@ public final class UnitCubeMesh {
|
||||
|
||||
CubeInstancedAttribs.enableInstanceArrays();
|
||||
|
||||
GLStateManager.glBindVertexArray(savedVAO);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
GLSMVertexInput.glBindVertexArray(savedVAO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
}
|
||||
|
||||
private static void attrib(int loc, int size, int type, boolean normalized, int offset) {
|
||||
GLStateManager.glEnableVertexAttribArray(loc);
|
||||
GLStateManager.glVertexAttribPointer(loc, size, type, normalized, VERTEX_STRIDE, offset);
|
||||
GLSMVertexInput.glEnableVertexAttribArray(loc);
|
||||
GLSMVertexInput.glVertexAttribPointer(loc, size, type, normalized, VERTEX_STRIDE, offset);
|
||||
}
|
||||
|
||||
public static void delete() {
|
||||
if (vbo != 0) {
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
GLSMBuffers.glDeleteBuffers(vbo);
|
||||
vbo = 0;
|
||||
}
|
||||
if (vao != 0) {
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
GLSMVertexInput.glDeleteVertexArrays(vao);
|
||||
vao = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLTypes;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
@@ -122,15 +123,63 @@ public final class VAOManager {
|
||||
private int clientSideEnabledCount = 0;
|
||||
private int arrayVersion = 0;
|
||||
private int versionClock = 0;
|
||||
private static final int DELETED_NAME_PRUNE_THRESHOLD = 4096;
|
||||
private static final int DEAD_EPOCH = -1;
|
||||
private final int pruneThreshold;
|
||||
private int bufferEpoch = 0;
|
||||
private final Int2IntOpenHashMap bufferDeletedAt = new Int2IntOpenHashMap();
|
||||
|
||||
public VAOManager() {
|
||||
this(DELETED_NAME_PRUNE_THRESHOLD);
|
||||
}
|
||||
|
||||
VAOManager(int pruneThreshold) {
|
||||
this.pruneThreshold = pruneThreshold;
|
||||
}
|
||||
|
||||
private void touch() {
|
||||
arrayVersion = ++versionClock;
|
||||
}
|
||||
|
||||
private boolean isBufferLive(int buffer, int sinceEpoch) {
|
||||
return bufferDeletedAt.get(buffer) <= sinceEpoch;
|
||||
return buffer == 0 || bufferDeletedAt.get(buffer) <= sinceEpoch;
|
||||
}
|
||||
|
||||
private int retiredEpoch(int buffer, int epoch, boolean rebase) {
|
||||
if (rebase) return epoch == DEAD_EPOCH ? DEAD_EPOCH : 0;
|
||||
return isBufferLive(buffer, epoch) ? epoch : DEAD_EPOCH;
|
||||
}
|
||||
|
||||
private void retire(@Nullable Attrib[] slots, boolean rebase) {
|
||||
if (slots == null) return;
|
||||
for (final Attrib a : slots) {
|
||||
if (a != null) a.epoch = retiredEpoch(a.vboId, a.epoch, rebase);
|
||||
}
|
||||
}
|
||||
|
||||
private void retireAll(ClientArrays[] savedStack, boolean rebase) {
|
||||
for (final VAOData data : vaoMap.values()) {
|
||||
retire(data.attribs, rebase);
|
||||
retire(data.generic, rebase);
|
||||
retire(data.conventional, rebase);
|
||||
}
|
||||
retire(currentAttribs, rebase);
|
||||
retire(currentGeneric, rebase);
|
||||
retire(currentConventional, rebase);
|
||||
for (final ClientArrays saved : savedStack) {
|
||||
if (saved == null) continue;
|
||||
saved.vboEpoch = retiredEpoch(saved.boundVBO, saved.vboEpoch, rebase);
|
||||
saved.eboEpoch = retiredEpoch(saved.boundEBO, saved.eboEpoch, rebase);
|
||||
retire(saved.generic, rebase);
|
||||
retire(saved.conventional, rebase);
|
||||
}
|
||||
}
|
||||
|
||||
private void pruneDeletedNames(ClientArrays[] savedStack) {
|
||||
retireAll(savedStack, false);
|
||||
bufferDeletedAt.clear();
|
||||
retireAll(savedStack, true);
|
||||
bufferEpoch = 0;
|
||||
}
|
||||
|
||||
public boolean isBufferLive(Attrib a) {
|
||||
@@ -205,9 +254,10 @@ public final class VAOManager {
|
||||
return detached;
|
||||
}
|
||||
|
||||
public void onDeleteBuffer(int buffer) {
|
||||
public void onDeleteBuffer(int buffer, ClientArrays[] savedStack) {
|
||||
if (buffer == 0) return;
|
||||
bufferDeletedAt.put(buffer, ++bufferEpoch);
|
||||
if (bufferEpoch >= pruneThreshold) pruneDeletedNames(savedStack);
|
||||
if (currentAttribs != null) {
|
||||
boolean detached = detach(currentGeneric != null ? currentGeneric : currentAttribs, buffer);
|
||||
if (currentConventional != null) detached |= detach(currentConventional, buffer);
|
||||
@@ -446,7 +496,8 @@ public final class VAOManager {
|
||||
public int boundEBO;
|
||||
public int clientActiveTextureUnit;
|
||||
int arrayVersion;
|
||||
int bufferEpoch;
|
||||
int vboEpoch;
|
||||
int eboEpoch;
|
||||
int vertexFlags;
|
||||
int genericEnabled;
|
||||
int conventionalEnabled;
|
||||
@@ -462,13 +513,18 @@ public final class VAOManager {
|
||||
saved[i].copyPointer(source);
|
||||
}
|
||||
|
||||
public boolean isBufferLive(int buffer, ClientArrays saved) {
|
||||
return isBufferLive(buffer, saved.bufferEpoch);
|
||||
public boolean isSavedVboLive(ClientArrays saved) {
|
||||
return isBufferLive(saved.boundVBO, saved.vboEpoch);
|
||||
}
|
||||
|
||||
public boolean isSavedEboLive(ClientArrays saved) {
|
||||
return isBufferLive(saved.boundEBO, saved.eboEpoch);
|
||||
}
|
||||
|
||||
public void saveClientArrays(ClientArrays out) {
|
||||
out.arrayVersion = arrayVersion;
|
||||
out.bufferEpoch = bufferEpoch;
|
||||
out.vboEpoch = bufferEpoch;
|
||||
out.eboEpoch = bufferEpoch;
|
||||
out.vertexFlags = currentVertexFlags;
|
||||
out.genericEnabled = genericEnabled;
|
||||
out.conventionalEnabled = conventionalEnabled;
|
||||
@@ -630,8 +686,8 @@ public final class VAOManager {
|
||||
clientArraysVBO = RENDER_BACKEND.genBuffers();
|
||||
}
|
||||
|
||||
final int savedVBO = GLStateManager.getBoundVBO();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, clientArraysVBO);
|
||||
final int savedVBO = GLSMBuffers.getBoundVBO();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, clientArraysVBO);
|
||||
|
||||
if (totalBytes > clientArraysVBOCapacity) {
|
||||
int newCap = Math.max(4096, clientArraysVBOCapacity);
|
||||
@@ -651,7 +707,7 @@ public final class VAOManager {
|
||||
}
|
||||
}
|
||||
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@ package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.MatrixHelper;
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMRasterizer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TexGenState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
|
||||
import org.joml.Matrix4f;
|
||||
@@ -51,6 +54,7 @@ public final class VertexKey {
|
||||
private static final int BIT_UNIT23_UV_FROM_UNIT0 = BIT_UNIT_TEXMAT_BASE + MAX_UNITS;
|
||||
private static final int BIT_LINE_STIPPLE = BIT_UNIT23_UV_FROM_UNIT0 + 1;
|
||||
private static final int BIT_INSTANCING = BIT_LINE_STIPPLE + 1;
|
||||
private static final int BIT_CLIP_EMULATED = BIT_INSTANCING + 3;
|
||||
private static final long INSTANCING_MASK = 0x7L;
|
||||
|
||||
static {
|
||||
@@ -103,6 +107,7 @@ public final class VertexKey {
|
||||
public int texGenModeQ() { return (int)((packed >> BIT_TEXGEN_Q) & 0x7); }
|
||||
public boolean texGenEnabled() { return texGenModeS() != TG_NONE || texGenModeT() != TG_NONE || texGenModeR() != TG_NONE || texGenModeQ() != TG_NONE; }
|
||||
public boolean clipPlanesEnabled() { return bit(BIT_CLIP_PLANES); }
|
||||
public boolean clipEmulated() { return bit(BIT_CLIP_EMULATED); }
|
||||
public boolean lineStipple() { return bit(BIT_LINE_STIPPLE); }
|
||||
public boolean lineQuads() { return bit(BIT_LINE_QUADS); }
|
||||
public Instancing instancing() { return Instancing.VALUES[(int) ((packed >> BIT_INSTANCING) & INSTANCING_MASK)]; }
|
||||
@@ -230,12 +235,13 @@ public final class VertexKey {
|
||||
if (hasTexCoord) bits |= (1L << BIT_HAS_VERTEX_TEX);
|
||||
if (hasLightmap) bits |= (1L << BIT_HAS_VERTEX_LIGHTMAP);
|
||||
|
||||
if (GLStateManager.consumeUnit23TexCoordSetDuringDraw(glCtx) && hasTexCoord) {
|
||||
if (GLSMCurrentAttribs.consumeUnit23TexCoordSetDuringDraw(glCtx) && hasTexCoord) {
|
||||
bits |= (1L << BIT_UNIT23_UV_FROM_UNIT0);
|
||||
}
|
||||
|
||||
if (GLStateManager.anyClipPlaneEnabled(glCtx)) {
|
||||
if (GLSMRasterizer.anyClipPlaneEnabled(glCtx)) {
|
||||
bits |= (1L << BIT_CLIP_PLANES);
|
||||
if (RenderSystem.isClipDistanceEmulated()) bits |= 1L << BIT_CLIP_EMULATED;
|
||||
}
|
||||
|
||||
if (glCtx.lineStippleActive) {
|
||||
@@ -277,6 +283,6 @@ public final class VertexKey {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("FFPVertexKey[0x%012X: lit=%b l0=%b l1=%b cm=%b fog=%b tex=%d%d%d%d texmat=%d%d%d%d col=%b nrm=%b vtex=%b vlm=%b tg=%d/%d/%d/%d clip=%b lquads=%b inst=%s]", packed,lightingEnabled(), lightEnabled(0), lightEnabled(1), colorMaterialEnabled(), fogEnabled(), unitTexCoordEnabled(0)?1:0, unitTexCoordEnabled(1)?1:0, unitTexCoordEnabled(2)?1:0, unitTexCoordEnabled(3)?1:0, unitTexMatEnabled(0)?1:0, unitTexMatEnabled(1)?1:0, unitTexMatEnabled(2)?1:0, unitTexMatEnabled(3)?1:0, hasVertexColor(), hasVertexNormal(), hasVertexTexCoord(), hasVertexLightmap(), texGenModeS(), texGenModeT(), texGenModeR(), texGenModeQ(), clipPlanesEnabled(), lineQuads(), instancing());
|
||||
return String.format("FFPVertexKey[0x%012X: lit=%b l0=%b l1=%b cm=%b fog=%b tex=%d%d%d%d texmat=%d%d%d%d col=%b nrm=%b vtex=%b vlm=%b tg=%d/%d/%d/%d clip=%b clipEmu=%b lquads=%b inst=%s]", packed,lightingEnabled(), lightEnabled(0), lightEnabled(1), colorMaterialEnabled(), fogEnabled(), unitTexCoordEnabled(0)?1:0, unitTexCoordEnabled(1)?1:0, unitTexCoordEnabled(2)?1:0, unitTexCoordEnabled(3)?1:0, unitTexMatEnabled(0)?1:0, unitTexMatEnabled(1)?1:0, unitTexMatEnabled(2)?1:0, unitTexMatEnabled(3)?1:0, hasVertexColor(), hasVertexNormal(), hasVertexTexCoord(), hasVertexLightmap(), texGenModeS(), texGenModeT(), texGenModeR(), texGenModeQ(), clipPlanesEnabled(), clipEmulated(), lineQuads(), instancing());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement;
|
||||
import org.embeddedt.embeddium.impl.render.shader.ShaderLoader;
|
||||
|
||||
/**
|
||||
* Generates GLSL 330 core vertex shaders for FFP emulation.
|
||||
@@ -19,6 +20,9 @@ public final class VertexShaderGenerator {
|
||||
emitAttributes(sb, key);
|
||||
emitUniforms(sb, key);
|
||||
emitOutputs(sb, key);
|
||||
if (key.lineQuads()) {
|
||||
sb.append(ShaderLoader.getShaderSource("angelica:include/line_quads.glsl")).append('\n');
|
||||
}
|
||||
|
||||
sb.append("void main() {\n");
|
||||
if (key.instancing() == Instancing.WEATHER) {
|
||||
@@ -100,13 +104,16 @@ public final class VertexShaderGenerator {
|
||||
private static void emitOutputs(StringBuilder sb, VertexKey key) {
|
||||
sb.append("// Outputs\n");
|
||||
sb.append("out vec4 v_Color;\n");
|
||||
sb.append("invariant gl_Position;\n");
|
||||
if (key.instancing().hasInstanceHead()) {
|
||||
sb.append("out vec4 v_Overlay;\n");
|
||||
sb.append("invariant gl_Position;\n");
|
||||
}
|
||||
if (key.lineStipple()) {
|
||||
sb.append("flat out vec2 v_LineStart;\n");
|
||||
}
|
||||
if (key.clipEmulated()) {
|
||||
sb.append(ClipDistanceGlsl.VS_OUT_DIST0).append('\n').append(ClipDistanceGlsl.VS_OUT_DIST1).append('\n');
|
||||
}
|
||||
if (key.separateSpecular()) {
|
||||
sb.append("out vec3 v_SpecularColor;\n");
|
||||
}
|
||||
@@ -142,7 +149,7 @@ public final class VertexShaderGenerator {
|
||||
} else {
|
||||
sb.append(" gl_Position = u_MVPMatrix * pos4;\n");
|
||||
if (key.lineQuads()) {
|
||||
emitLineQuadWidening(sb);
|
||||
emitLineQuadWidening(sb, key);
|
||||
}
|
||||
|
||||
// Eye position needed for lighting, fog, EYE_LINEAR texgen, and clip planes
|
||||
@@ -156,42 +163,15 @@ public final class VertexShaderGenerator {
|
||||
sb.append('\n');
|
||||
}
|
||||
|
||||
private static void emitLineQuadWidening(StringBuilder sb) {
|
||||
private static void emitLineQuadWidening(StringBuilder sb, VertexKey key) {
|
||||
sb.append(" int lineCorner = gl_VertexID % 6;\n");
|
||||
sb.append(" bool lineStart = lineCorner == 0 || lineCorner == 1 || lineCorner == 3;\n");
|
||||
sb.append(" bool lineStart = angelica_lineStart(lineCorner);\n");
|
||||
sb.append(" vec4 lineOther = u_MVPMatrix * vec4(a_LineOtherEnd, 1.0);\n");
|
||||
sb.append(" vec4 lineC0 = lineStart ? gl_Position : lineOther;\n");
|
||||
sb.append(" vec4 lineC1 = lineStart ? lineOther : gl_Position;\n");
|
||||
sb.append(" vec4 lineCenter = lineC0;\n");
|
||||
sb.append(" float lineT = 0.0;\n");
|
||||
sb.append(" float lineD0 = lineC0.z + lineC0.w;\n");
|
||||
sb.append(" float lineD1 = lineC1.z + lineC1.w;\n");
|
||||
sb.append(" if (lineD0 < 0.0 && lineD1 < 0.0) {\n");
|
||||
sb.append(" gl_Position = vec4(0.0, 0.0, 2.0, 1.0);\n");
|
||||
sb.append(" } else {\n");
|
||||
sb.append(" float lineT0 = lineD0 < 0.0 ? lineD0 / (lineD0 - lineD1) : 0.0;\n");
|
||||
sb.append(" float lineT1 = lineD1 < 0.0 ? lineD0 / (lineD0 - lineD1) : 1.0;\n");
|
||||
sb.append(" lineT = lineStart ? lineT0 : lineT1;\n");
|
||||
sb.append(" vec4 lineP0 = mix(lineC0, lineC1, lineT0);\n");
|
||||
sb.append(" vec4 lineP1 = mix(lineC0, lineC1, lineT1);\n");
|
||||
sb.append(" vec2 lineN0 = lineP0.xy / lineP0.w;\n");
|
||||
sb.append(" vec2 lineN1 = lineP1.xy / lineP1.w;\n");
|
||||
sb.append(" vec2 linePixel = 2.0 / u_ViewportSize;\n");
|
||||
sb.append(" float lineHalfWidth = 0.5 * u_LineWidth;\n");
|
||||
sb.append(" vec2 lineOffset;\n");
|
||||
sb.append(" vec2 lineShift;\n");
|
||||
sb.append(" vec2 lineSpan = abs(lineN1 - lineN0) * u_ViewportSize;\n");
|
||||
sb.append(" if (lineSpan.x > lineSpan.y) {\n");
|
||||
sb.append(" lineOffset = vec2(0.0, lineHalfWidth * linePixel.y);\n");
|
||||
sb.append(" lineShift = vec2(lineN0.x < lineN1.x ? -0.5 : 0.5, -0.125) * linePixel;\n");
|
||||
sb.append(" } else {\n");
|
||||
sb.append(" lineOffset = vec2(lineHalfWidth * linePixel.x, 0.0);\n");
|
||||
sb.append(" lineShift = vec2(0.125, lineN0.y < lineN1.y ? -0.5 : 0.5) * linePixel;\n");
|
||||
sb.append(" }\n");
|
||||
sb.append(" vec4 lineP = lineStart ? lineP0 : lineP1;\n");
|
||||
sb.append(" vec2 lineN = lineStart ? lineN0 : lineN1;\n");
|
||||
sb.append(" gl_Position = vec4((lineN + (lineCorner % 2 == 0 ? lineOffset : -lineOffset) + lineShift) * lineP.w, lineP.z, lineP.w);\n");
|
||||
sb.append(" }\n");
|
||||
if (key.lineStipple()) {
|
||||
sb.append(" vec4 lineCenter = lineStart ? gl_Position : lineOther;\n");
|
||||
}
|
||||
sb.append(" float lineT;\n");
|
||||
sb.append(" gl_Position = angelica_lineQuad(gl_Position, lineOther, lineCorner, u_ViewportSize, u_LineWidth, lineT);\n");
|
||||
}
|
||||
|
||||
private static void emitNormalTransform(StringBuilder sb, VertexKey key) {
|
||||
@@ -414,26 +394,26 @@ public final class VertexShaderGenerator {
|
||||
|
||||
private static void emitFogDistance(StringBuilder sb, VertexKey key) {
|
||||
sb.append(" // Fog distance\n");
|
||||
final String own = fogDistance(key, "eyePos");
|
||||
final String fog = key.lineQuads() ? acrossLine(own, fogDistance(key, "lineEyeOther")) : own;
|
||||
final String own = FfpGlsl.fogDistance(key.fogDistanceMode(), "eyePos");
|
||||
final String fog = key.lineQuads() ? acrossLine(own, FfpGlsl.fogDistance(key.fogDistanceMode(), "lineEyeOther")) : own;
|
||||
sb.append(" v_FogCoord = ").append(fog).append(";\n");
|
||||
}
|
||||
|
||||
// Mesa ffvertex_prog.c build_fog(): FDM_EYE_RADIAL/EYE_PLANE/EYE_PLANE_ABS
|
||||
private static String fogDistance(VertexKey key, String eye) {
|
||||
return switch (key.fogDistanceMode()) {
|
||||
case 0 -> "length(" + eye + ".xyz)"; // FDM_EYE_RADIAL: Euclidean distance
|
||||
case 1 -> eye + ".z"; // FDM_EYE_PLANE: raw Z (can be negative, clamped by fog factor)
|
||||
default -> "abs(" + eye + ".z)"; // FDM_EYE_PLANE_ABS: absolute Z
|
||||
};
|
||||
}
|
||||
|
||||
private static void emitClipDistances(StringBuilder sb, VertexKey key) {
|
||||
sb.append(" // Clip distances\n");
|
||||
final boolean emulated = key.clipEmulated();
|
||||
final String[] distances = emulated ? new String[8] : null;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
final String own = "dot(u_ClipPlane[" + i + "], eyePos)";
|
||||
final String distance = key.lineQuads() ? acrossLine(own, "dot(u_ClipPlane[" + i + "], lineEyeOther)") : own;
|
||||
sb.append(" gl_ClipDistance[").append(i).append("] = ").append(distance).append(";\n");
|
||||
if (emulated) {
|
||||
distances[i] = distance;
|
||||
} else {
|
||||
sb.append(" gl_ClipDistance[").append(i).append("] = ").append(distance).append(";\n");
|
||||
}
|
||||
}
|
||||
if (emulated) {
|
||||
ClipDistanceGlsl.appendVsAssign(sb, distances);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+51
-6
@@ -1,33 +1,78 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* One rain or snow column per instance.
|
||||
* One weather column per instance.
|
||||
*/
|
||||
public final class WeatherInstancedAttribs {
|
||||
|
||||
public static final int LOC_COLUMN_SPAN = ParticleInstancedAttribs.LOC_CENTER_HALF;
|
||||
public static final int LOC_JITTER = ParticleInstancedAttribs.LOC_UV;
|
||||
public static final int LOC_PARAMS = InstancedAttribs.LOC_COLOR;
|
||||
public static final int LOC_COLOR = InstancedAttribs.LOC_ROW2;
|
||||
public static final int LOC_LAYER = InstancedAttribs.LOC_OVERLAY;
|
||||
|
||||
public static final int OFFSET_COLUMN_SPAN = 0;
|
||||
public static final int OFFSET_JITTER = 16;
|
||||
public static final int OFFSET_PARAMS = 32;
|
||||
public static final int STRIDE = 48;
|
||||
public static final int OFFSET_COLOR = 48;
|
||||
public static final int OFFSET_LAYER = 64;
|
||||
public static final int STRIDE = 80;
|
||||
|
||||
public static final int RAIN_PERIOD = 32;
|
||||
public static final float RAIN_SCROLL_BASE = 3.0F;
|
||||
public static final float RAIN_FADE = 0.5F;
|
||||
public static final int SNOW_PERIOD = 512;
|
||||
public static final float SNOW_U_DRIFT = 0.01F;
|
||||
public static final float SNOW_V_DRIFT = 0.001F;
|
||||
public static final float SNOW_FADE = 0.3F;
|
||||
public static final float SOURCE_VANILLA = 0.0F;
|
||||
public static final float SOURCE_PROVIDER = 1.0F;
|
||||
|
||||
public static void putColumn(ByteBuffer data, int index, float x, float z, float bottom, float top, float uBase, float uDrift,
|
||||
float vBase, float vDrift, float brightness, int scrollOffset, float scrollScale, float source, float r, float g, float b,
|
||||
float a, int period, float uDriftScale, float vDriftScale, float fadeScale) {
|
||||
final int base = index * STRIDE;
|
||||
data.putFloat(base + OFFSET_COLUMN_SPAN, x);
|
||||
data.putFloat(base + OFFSET_COLUMN_SPAN + 4, z);
|
||||
data.putFloat(base + OFFSET_COLUMN_SPAN + 8, bottom);
|
||||
data.putFloat(base + OFFSET_COLUMN_SPAN + 12, top);
|
||||
data.putFloat(base + OFFSET_JITTER, uBase);
|
||||
data.putFloat(base + OFFSET_JITTER + 4, uDrift);
|
||||
data.putFloat(base + OFFSET_JITTER + 8, vBase);
|
||||
data.putFloat(base + OFFSET_JITTER + 12, vDrift);
|
||||
data.putFloat(base + OFFSET_PARAMS, brightness);
|
||||
data.putFloat(base + OFFSET_PARAMS + 4, scrollOffset & (period - 1));
|
||||
data.putFloat(base + OFFSET_PARAMS + 8, scrollScale);
|
||||
data.putFloat(base + OFFSET_PARAMS + 12, source);
|
||||
data.putFloat(base + OFFSET_COLOR, r);
|
||||
data.putFloat(base + OFFSET_COLOR + 4, g);
|
||||
data.putFloat(base + OFFSET_COLOR + 8, b);
|
||||
data.putFloat(base + OFFSET_COLOR + 12, a);
|
||||
data.putFloat(base + OFFSET_LAYER, period);
|
||||
data.putFloat(base + OFFSET_LAYER + 4, uDriftScale);
|
||||
data.putFloat(base + OFFSET_LAYER + 8, vDriftScale);
|
||||
data.putFloat(base + OFFSET_LAYER + 12, fadeScale);
|
||||
}
|
||||
|
||||
public static void pointInstanceAttribs(long base) {
|
||||
GLStateManager.glVertexAttribPointer(LOC_COLUMN_SPAN, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_COLUMN_SPAN);
|
||||
GLStateManager.glVertexAttribPointer(LOC_JITTER, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_JITTER);
|
||||
GLStateManager.glVertexAttribPointer(LOC_PARAMS, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_PARAMS);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_COLUMN_SPAN, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_COLUMN_SPAN);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_JITTER, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_JITTER);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_PARAMS, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_PARAMS);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_COLOR, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_COLOR);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_LAYER, 4, GL11.GL_FLOAT, false, STRIDE, base + OFFSET_LAYER);
|
||||
}
|
||||
|
||||
static void enableInstanceArrays() {
|
||||
InstancedAttribs.enableInstanced(LOC_COLUMN_SPAN);
|
||||
InstancedAttribs.enableInstanced(LOC_JITTER);
|
||||
InstancedAttribs.enableInstanced(LOC_PARAMS);
|
||||
InstancedAttribs.enableInstanced(LOC_COLOR);
|
||||
InstancedAttribs.enableInstanced(LOC_LAYER);
|
||||
}
|
||||
|
||||
private WeatherInstancedAttribs() {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
/**
|
||||
* The per-frame half of the rain and snow instancing, set once per weather draw.
|
||||
* The per-frame half of the weather column instancing, set once per frame.
|
||||
*/
|
||||
public final class WeatherParams {
|
||||
|
||||
@@ -15,9 +15,14 @@ public final class WeatherParams {
|
||||
public static float partialTicks;
|
||||
public static float age;
|
||||
|
||||
public static float rainScroll;
|
||||
public static float snowScroll;
|
||||
public static float vanillaTick;
|
||||
public static float providerTick;
|
||||
public static float rainStrength;
|
||||
public static float providerAge;
|
||||
|
||||
public static float providerInvRadius;
|
||||
|
||||
public static final int TICK_WRAP = 1024;
|
||||
|
||||
public static int generation;
|
||||
|
||||
@@ -25,7 +30,7 @@ public final class WeatherParams {
|
||||
|
||||
public static void set(float translateX, float translateY, float translateZ, float invRadius,
|
||||
float cameraFracX, float cameraFracZ, float partialTicks, float age,
|
||||
float rainScroll, float snowScroll, float rainStrength) {
|
||||
int vanillaTick, float rainStrength, int providerTick, float providerAge, float providerInvRadius) {
|
||||
WeatherParams.translateX = translateX;
|
||||
WeatherParams.translateY = translateY;
|
||||
WeatherParams.translateZ = translateZ;
|
||||
@@ -34,9 +39,11 @@ public final class WeatherParams {
|
||||
WeatherParams.cameraFracZ = cameraFracZ;
|
||||
WeatherParams.partialTicks = partialTicks;
|
||||
WeatherParams.age = age;
|
||||
WeatherParams.rainScroll = rainScroll;
|
||||
WeatherParams.snowScroll = snowScroll;
|
||||
WeatherParams.vanillaTick = vanillaTick & (TICK_WRAP - 1);
|
||||
WeatherParams.providerTick = providerTick & (TICK_WRAP - 1);
|
||||
WeatherParams.rainStrength = rainStrength;
|
||||
WeatherParams.providerAge = providerAge;
|
||||
WeatherParams.providerInvRadius = providerInvRadius;
|
||||
generation++;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@ package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
|
||||
@@ -10,7 +11,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* The four corners every rain and snow column is expanded from. x picks the end of the billboard, y picks
|
||||
* The four corners every weather column is expanded from. x picks the end of the billboard, y picks
|
||||
* the bottom or top edge.
|
||||
*/
|
||||
public final class WeatherQuadMesh {
|
||||
@@ -32,37 +33,29 @@ public final class WeatherQuadMesh {
|
||||
for (float corner : CORNERS) data.putFloat(corner);
|
||||
data.flip();
|
||||
|
||||
vao = GLStateManager.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
vbo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glBufferData(GL15.GL_ARRAY_BUFFER, data, GL15.GL_STATIC_DRAW);
|
||||
vao = GLSMVertexInput.glGenVertexArrays();
|
||||
GLSMVertexInput.glBindVertexArray(vao);
|
||||
vbo = GLSMBuffers.glGenBuffers();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLSMBuffers.glBufferData(GL15.GL_ARRAY_BUFFER, data, GL15.GL_STATIC_DRAW);
|
||||
|
||||
final int corner = VertexFormatElement.Usage.PRIMARY_UV.getAttributeLocation();
|
||||
GLStateManager.glEnableVertexAttribArray(corner);
|
||||
GLStateManager.glVertexAttribPointer(corner, 2, GL11.GL_FLOAT, false, 2 * Float.BYTES, 0L);
|
||||
GLSMVertexInput.glEnableVertexAttribArray(corner);
|
||||
GLSMVertexInput.glVertexAttribPointer(corner, 2, GL11.GL_FLOAT, false, 2 * Float.BYTES, 0L);
|
||||
WeatherInstancedAttribs.enableInstanceArrays();
|
||||
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLSMVertexInput.glBindVertexArray(0);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
return vao;
|
||||
}
|
||||
|
||||
public static void bindInstanceBuffer(int bufferId) {
|
||||
GLStateManager.glBindVertexArray(vao());
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferId);
|
||||
WeatherInstancedAttribs.pointInstanceAttribs(0L);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
public static void delete() {
|
||||
if (vbo != 0) {
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
GLSMBuffers.glDeleteBuffers(vbo);
|
||||
vbo = 0;
|
||||
}
|
||||
if (vao != 0) {
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
GLSMVertexInput.glDeleteVertexArrays(vao);
|
||||
vao = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.glsm.hooks;
|
||||
|
||||
public interface DeferredAlphaHandler {
|
||||
boolean isAlphaTestLocked();
|
||||
boolean isOverrideHeld();
|
||||
boolean deferAlphaTestToggle(boolean enabled);
|
||||
boolean deferAlphaFunc(int function, float reference);
|
||||
}
|
||||
@@ -3,8 +3,10 @@ package com.gtnewhorizons.angelica.glsm.hooks;
|
||||
import com.gtnewhorizons.angelica.glsm.CaptureGate;
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLDebug;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMTextureLifetime;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.profiling.Tracy;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
@@ -15,17 +17,25 @@ public final class FrameHooks {
|
||||
private static boolean gameLoopStarted;
|
||||
private static long frameCounter;
|
||||
private static boolean frameGroupActive;
|
||||
private static String framePrefix = "frame:";
|
||||
private static String buildLabel = "";
|
||||
|
||||
public static void bootstrapFirstFrame() {
|
||||
DisplayListManager.abortIfLeaked();
|
||||
if (!gameLoopStarted) {
|
||||
gameLoopStarted = true;
|
||||
final GLSMInitConfig config = GLStateManager.getInitConfig();
|
||||
if (config != null && !config.getBuildLabel().isEmpty()) {
|
||||
buildLabel = config.getBuildLabel();
|
||||
framePrefix = buildLabel + " frame:";
|
||||
}
|
||||
RENDER_BACKEND.onFrameBegin();
|
||||
pushFrameGroup();
|
||||
}
|
||||
}
|
||||
|
||||
public static void frameEnd() {
|
||||
GLSMTextureLifetime.onFrameEnd();
|
||||
popFrameGroup();
|
||||
RENDER_BACKEND.onFrameEnd();
|
||||
}
|
||||
@@ -46,8 +56,10 @@ public final class FrameHooks {
|
||||
}
|
||||
|
||||
private static void pushFrameGroup() {
|
||||
final boolean wasConnected = CaptureGate.tracyConnected;
|
||||
CaptureGate.refresh();
|
||||
GLDebug.pushGroup("frame:", frameCounter);
|
||||
if (CaptureGate.tracyConnected && !wasConnected && !buildLabel.isEmpty()) Tracy.message(buildLabel);
|
||||
GLDebug.pushGroup(framePrefix, frameCounter);
|
||||
frameGroupActive = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ public final class GLSMHooks {
|
||||
public static final EventBus<ProgramDeleteEvent> PROGRAM_DELETE = EventBus.create(ProgramDeleteEvent.class);
|
||||
public static final EventBus<BlendFuncChangeEvent> BLEND_FUNC_CHANGE = EventBus.create(BlendFuncChangeEvent.class);
|
||||
public static final EventBus<FogStateChangeEvent> FOG_STATE_CHANGE = EventBus.create(FogStateChangeEvent.class);
|
||||
public static final EventBus<ClipPlanesInUseEvent> CLIP_PLANES_IN_USE = EventBus.create(ClipPlanesInUseEvent.class);
|
||||
public static final EventBus<LightmapCoordsEvent> LIGHTMAP_COORDS = EventBus.create(LightmapCoordsEvent.class);
|
||||
public static final EventBus<AlphaStateChangeEvent> ALPHA_STATE_CHANGE = EventBus.create(AlphaStateChangeEvent.class);
|
||||
public static final EventBus<ShaderColorChangeEvent> SHADER_COLOR_CHANGE = EventBus.create(ShaderColorChangeEvent.class);
|
||||
@@ -46,6 +47,7 @@ public final class GLSMHooks {
|
||||
public static final ProgramDeleteEvent programDeleteEvent = new ProgramDeleteEvent();
|
||||
public static final BlendFuncChangeEvent blendFuncChangeEvent = new BlendFuncChangeEvent();
|
||||
public static final FogStateChangeEvent fogStateChangeEvent = new FogStateChangeEvent();
|
||||
public static final ClipPlanesInUseEvent clipPlanesInUseEvent = new ClipPlanesInUseEvent();
|
||||
public static final LightmapCoordsEvent lightmapCoordsEvent = new LightmapCoordsEvent();
|
||||
public static final AlphaStateChangeEvent alphaStateChangeEvent = new AlphaStateChangeEvent();
|
||||
public static final ShaderColorChangeEvent shaderColorChangeEvent = new ShaderColorChangeEvent();
|
||||
|
||||
@@ -17,6 +17,7 @@ public final class GLSMInitConfig {
|
||||
@Getter private final Runnable postInitCallback;
|
||||
private final boolean dsaEnabled;
|
||||
@Getter private final boolean noErrorChecks;
|
||||
@Getter private final String buildLabel;
|
||||
|
||||
private GLSMInitConfig(Builder builder) {
|
||||
this.lwjglDebug = builder.lwjglDebug;
|
||||
@@ -27,6 +28,7 @@ public final class GLSMInitConfig {
|
||||
this.displayHeight = builder.displayHeight;
|
||||
this.postInitCallback = builder.postInitCallback;
|
||||
this.dsaEnabled = builder.dsaEnabled;
|
||||
this.buildLabel = builder.buildLabel;
|
||||
}
|
||||
|
||||
public boolean isDSAEnabled() {
|
||||
@@ -46,6 +48,7 @@ public final class GLSMInitConfig {
|
||||
private Runnable postInitCallback = null;
|
||||
private boolean dsaEnabled = true;
|
||||
private boolean noErrorChecks;
|
||||
private String buildLabel = "";
|
||||
|
||||
private Builder() {}
|
||||
|
||||
@@ -85,6 +88,11 @@ public final class GLSMInitConfig {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder buildLabel(String buildLabel) {
|
||||
this.buildLabel = buildLabel == null ? "" : buildLabel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public GLSMInitConfig build() {
|
||||
return new GLSMInitConfig(this);
|
||||
}
|
||||
|
||||
+6
-6
@@ -2,7 +2,7 @@ package com.gtnewhorizons.angelica.glsm.hooks;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.InstancedAttribs;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@@ -65,14 +65,14 @@ public interface ImmediateExtendedAttribHandler {
|
||||
}
|
||||
|
||||
static void setupExtAttribPointers(long baseOffset, int stride) {
|
||||
GLStateManager.glEnableVertexAttribArray(LOC_MID_TEX);
|
||||
GLStateManager.glVertexAttribPointer(LOC_MID_TEX, 2, GL11.GL_FLOAT, false, stride, baseOffset);
|
||||
GLStateManager.glEnableVertexAttribArray(LOC_TANGENT);
|
||||
GLStateManager.glVertexAttribPointer(LOC_TANGENT, 4, GL11.GL_BYTE, true, stride, baseOffset + 8);
|
||||
GLSMVertexInput.glEnableVertexAttribArray(LOC_MID_TEX);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_MID_TEX, 2, GL11.GL_FLOAT, false, stride, baseOffset);
|
||||
GLSMVertexInput.glEnableVertexAttribArray(LOC_TANGENT);
|
||||
GLSMVertexInput.glVertexAttribPointer(LOC_TANGENT, 4, GL11.GL_BYTE, true, stride, baseOffset + 8);
|
||||
}
|
||||
|
||||
static void setupEntityIdsPointer(long offset, int stride) {
|
||||
GLStateManager.glEnableVertexAttribArray(LOC_ENTITY_IDS);
|
||||
GLSMVertexInput.glEnableVertexAttribArray(LOC_ENTITY_IDS);
|
||||
InstancedAttribs.pointEntityIds(LOC_ENTITY_IDS, stride, offset);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.glsm.hooks;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMTextures;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
@@ -26,12 +27,12 @@ public final class TextureUtilHooks {
|
||||
private TextureUtilHooks() {}
|
||||
|
||||
public static void setMaxLevel(int mipmapLevels) {
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, mipmapLevels);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, mipmapLevels);
|
||||
}
|
||||
|
||||
public static void captureBoundFilterTexture() {
|
||||
final GLContextState ctx = GLStateManager.ctx();
|
||||
final int id = GLStateManager.getBoundTextureForServerState();
|
||||
final int id = GLSMTextures.getBoundTextureForServerState();
|
||||
ctx.savedFilterTextureId = id;
|
||||
final TextureInfo info = TextureInfoCache.INSTANCE.getInfo(id);
|
||||
if (info != null) {
|
||||
@@ -47,14 +48,39 @@ public final class TextureUtilHooks {
|
||||
GLStateManager.ctx().savedFilterTextureId = 0;
|
||||
}
|
||||
|
||||
public static boolean beginFilterSave(boolean blurred, boolean mipmap, float aniso) {
|
||||
captureBoundFilterTexture();
|
||||
return GLStateManager.beginExitTextureFilter(!blurred && !mipmap && aniso == 1);
|
||||
}
|
||||
|
||||
public static void endFilterSave(boolean captured) {
|
||||
if (captured) GLStateManager.finishExitTextureFilterSave();
|
||||
}
|
||||
|
||||
public static boolean beginFilterRestore() {
|
||||
return GLStateManager.beginExitTextureFilterRestore();
|
||||
}
|
||||
|
||||
public static void endFilterRestore(boolean captured) {
|
||||
try {
|
||||
if (captured) GLStateManager.finishExitTextureFilterRestore();
|
||||
} finally {
|
||||
clearSavedFilterTexture();
|
||||
}
|
||||
}
|
||||
|
||||
public static void filterFailed(boolean captured) {
|
||||
if (captured) GLStateManager.failExitTextureFilter();
|
||||
}
|
||||
|
||||
public static void restoreFilter(int min, int mag) {
|
||||
final int id = GLStateManager.ctx().savedFilterTextureId;
|
||||
if (id != 0 && DisplayListManager.getRecordMode() == DisplayListManager.RecordMode.NONE) {
|
||||
RenderSystem.texParameteri(id, GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, min);
|
||||
RenderSystem.texParameteri(id, GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, mag);
|
||||
} else {
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, min);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, mag);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, min);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, mag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +89,7 @@ public final class TextureUtilHooks {
|
||||
if (id != 0 && DisplayListManager.getRecordMode() == DisplayListManager.RecordMode.NONE) {
|
||||
RenderSystem.texParameterf(id, GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
|
||||
} else {
|
||||
GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
|
||||
GLSMTextures.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +117,7 @@ public final class TextureUtilHooks {
|
||||
|
||||
/** TextureUtil.func_152777_a(false, false, 1) without using vanilla's single save slot, which the caller may hold. */
|
||||
public static void forceNearestFilter() {
|
||||
final int id = GLStateManager.getBoundTextureForServerState();
|
||||
final int id = GLSMTextures.getBoundTextureForServerState();
|
||||
final TextureInfo info = id != 0 ? TextureInfoCache.INSTANCE.getInfo(id) : null;
|
||||
if (info == null) {
|
||||
nearestTexture = 0;
|
||||
@@ -118,9 +144,9 @@ public final class TextureUtilHooks {
|
||||
RenderSystem.texParameteri(id, GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, mag);
|
||||
if (anisotropic) RenderSystem.texParameterf(id, GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
|
||||
} else {
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, min);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, mag);
|
||||
if (anisotropic) GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, min);
|
||||
GLSMTextures.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, mag);
|
||||
if (anisotropic) GLSMTextures.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.glsm.hooks.events;
|
||||
|
||||
import net.minecraftforge.eventbus.api.event.MutableEvent;
|
||||
|
||||
public final class ClipPlanesInUseEvent extends MutableEvent {}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.loading;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.redirect.GLSMRedirector;
|
||||
import com.gtnewhorizons.angelica.glsm.redirect.LegacyRewriter;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
@@ -30,6 +31,14 @@ public class ModRedirector {
|
||||
this.allExclusions = exclusions.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public void setLegacyHint(String hint) {
|
||||
core.setLegacyHint(hint);
|
||||
}
|
||||
|
||||
public void setLegacyRewriter(LegacyRewriter rewriter) {
|
||||
core.setLegacyRewriter(rewriter);
|
||||
}
|
||||
|
||||
public ClassDump getDump() {
|
||||
return dump;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ public final class DebugCounters {
|
||||
public static final LongAdder TRANSFER_WAIT_NANOS = new LongAdder();
|
||||
public static final LongAdder PRESENTS = new LongAdder();
|
||||
public static final LongAdder EMPTY_ACQUIRES = new LongAdder();
|
||||
public static final LongAdder PBR_ANIM_UPDATES = new LongAdder();
|
||||
public static final LongAdder PBR_ANIM_DRY_RUNS = new LongAdder();
|
||||
|
||||
private DebugCounters() {}
|
||||
}
|
||||
@@ -152,11 +152,11 @@ public final class Tracy {
|
||||
return backend;
|
||||
}
|
||||
|
||||
private static final String ABI_SENTINEL = "sectionEnter";
|
||||
private static final String ABI_SENTINEL = "frameImage";
|
||||
|
||||
private static boolean implementsCurrentAbi(TracyBackend backend) {
|
||||
try {
|
||||
backend.getClass().getMethod(ABI_SENTINEL, int.class, String.class);
|
||||
backend.getClass().getMethod(ABI_SENTINEL, long.class, int.class, int.class, int.class, boolean.class);
|
||||
return true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
LOGGER.warn("Tracy backend {} was built against an older TracyBackend interface; profiling disabled", backend.getClass().getName());
|
||||
@@ -337,6 +337,12 @@ public final class Tracy {
|
||||
if (ptr != 0) BACKEND.frameMark(ptr);
|
||||
}
|
||||
|
||||
/** Copies {@code rgba} before returning; width and height must be multiples of 4. */
|
||||
public static void frameImage(long rgba, int width, int height, int offset, boolean flip) {
|
||||
if (!ENABLED || SHUTTING_DOWN) return;
|
||||
BACKEND.frameImage(rgba, width, height, offset, flip);
|
||||
}
|
||||
|
||||
public static void plotInt(String name, long value) {
|
||||
plotInt(name, value, TracyBackend.PLOT_FORMAT_NUMBER);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public interface TracyBackend {
|
||||
|
||||
void frameMark();
|
||||
void frameMark(long namePtr);
|
||||
void frameImage(long rgba, int width, int height, int offset, boolean flip);
|
||||
|
||||
long internFrameName(String name);
|
||||
long internPlotName(String name, int format);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLTypes;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
@@ -67,7 +68,7 @@ public final class AttribSnapshot {
|
||||
public static AttribSnapshot snapshot(int firstVertex, int vertexCount) {
|
||||
final AttribDesc[] out = new AttribDesc[VAOManager.MAX_ATTRIBS];
|
||||
final List<ByteBuffer> allocated = new ArrayList<>();
|
||||
final int prevVBO = GLStateManager.getBoundVBO();
|
||||
final int prevVBO = GLSMBuffers.getBoundVBO();
|
||||
final VAOManager vaos = GLStateManager.ctx().vaos;
|
||||
boolean success = false;
|
||||
|
||||
@@ -133,8 +134,8 @@ public final class AttribSnapshot {
|
||||
}
|
||||
|
||||
if (buf == null) {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, a.vboId);
|
||||
final int bufferSize = GLStateManager.glGetBufferParameteri(GL15.GL_ARRAY_BUFFER, GL15.GL_BUFFER_SIZE);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, a.vboId);
|
||||
final int bufferSize = GLSMBuffers.glGetBufferParameteri(GL15.GL_ARRAY_BUFFER, GL15.GL_BUFFER_SIZE);
|
||||
if (bufferSize <= 0) {
|
||||
warnOnce("vbo-orphaned", "[AttribSnapshot] GL_BUFFER_SIZE={} for VBO {} -- skipping capture", bufferSize, a.vboId);
|
||||
return null;
|
||||
@@ -162,7 +163,7 @@ public final class AttribSnapshot {
|
||||
}
|
||||
|
||||
buf = MemoryUtilities.memAlloc(rs);
|
||||
GLStateManager.glGetBufferSubData(GL15.GL_ARRAY_BUFFER, ro, buf);
|
||||
GLSMBuffers.glGetBufferSubData(GL15.GL_ARRAY_BUFFER, ro, buf);
|
||||
allocated.add(buf);
|
||||
readOffset = ro;
|
||||
|
||||
@@ -190,7 +191,7 @@ public final class AttribSnapshot {
|
||||
success = true;
|
||||
return new AttribSnapshot(out, allocated);
|
||||
} finally {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, prevVBO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, prevVBO);
|
||||
if (!success) {
|
||||
for (ByteBuffer b : allocated) MemoryUtilities.memFree(b);
|
||||
}
|
||||
|
||||
+83
-70
@@ -2,7 +2,20 @@ package com.gtnewhorizons.angelica.glsm.recording;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMAttribStack;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBlend;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMDepthStencilAlpha;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMEnable;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMFog;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMFramebuffer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMLighting;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMMatrices;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMPrograms;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMRasterizer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMTextures;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.commands.DisplayListCommand;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
@@ -57,77 +70,77 @@ public final class CommandBufferExecutor {
|
||||
switch (cmd) {
|
||||
// === Single int commands ===
|
||||
case GLCommand.ENABLE -> {
|
||||
GLStateManager.glEnable(memGetInt(ptr));
|
||||
GLSMEnable.glEnable(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.DISABLE -> {
|
||||
GLStateManager.glDisable(memGetInt(ptr));
|
||||
GLSMEnable.glDisable(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.CLEAR -> {
|
||||
GLStateManager.glClear(memGetInt(ptr));
|
||||
GLSMFramebuffer.glClear(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.CLEAR_STENCIL -> {
|
||||
GLStateManager.glClearStencil(memGetInt(ptr));
|
||||
GLSMDepthStencilAlpha.glClearStencil(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.CULL_FACE -> {
|
||||
GLStateManager.glCullFace(memGetInt(ptr));
|
||||
GLSMRasterizer.glCullFace(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.DEPTH_FUNC -> {
|
||||
GLStateManager.glDepthFunc(memGetInt(ptr));
|
||||
GLSMDepthStencilAlpha.glDepthFunc(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.SHADE_MODEL -> {
|
||||
GLStateManager.glShadeModel(memGetInt(ptr));
|
||||
GLSMRasterizer.glShadeModel(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.LOGIC_OP -> {
|
||||
GLStateManager.glLogicOp(memGetInt(ptr));
|
||||
GLSMBlend.glLogicOp(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.MATRIX_MODE -> {
|
||||
GLStateManager.glMatrixMode(memGetInt(ptr));
|
||||
GLSMMatrices.glMatrixMode(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.ACTIVE_TEXTURE -> {
|
||||
GLStateManager.glActiveTexture(memGetInt(ptr));
|
||||
GLSMTextures.glActiveTexture(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.USE_PROGRAM -> {
|
||||
final int recordedProgram = memGetInt(ptr);
|
||||
GLStateManager.glUseProgram(compiledDisplayList.resolveProgram(recordedProgram));
|
||||
GLSMPrograms.glUseProgram(compiledDisplayList.resolveProgram(recordedProgram));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.PUSH_ATTRIB -> {
|
||||
GLStateManager.glPushAttrib(memGetInt(ptr));
|
||||
GLSMAttribStack.glPushAttrib(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.POP_ATTRIB -> {
|
||||
GLStateManager.glPopAttrib();
|
||||
GLSMAttribStack.glPopAttrib();
|
||||
ptr += 4; // Skip unused padding
|
||||
}
|
||||
case GLCommand.LOAD_IDENTITY -> {
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLSMMatrices.glLoadIdentity();
|
||||
}
|
||||
case GLCommand.PUSH_MATRIX -> {
|
||||
GLStateManager.glPushMatrix();
|
||||
GLSMMatrices.glPushMatrix();
|
||||
}
|
||||
case GLCommand.POP_MATRIX -> {
|
||||
GLStateManager.glPopMatrix();
|
||||
GLSMMatrices.glPopMatrix();
|
||||
}
|
||||
case GLCommand.STENCIL_MASK -> {
|
||||
GLStateManager.glStencilMask(memGetInt(ptr));
|
||||
GLSMDepthStencilAlpha.glStencilMask(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.DEPTH_MASK -> {
|
||||
GLStateManager.glDepthMask(memGetInt(ptr) != 0);
|
||||
GLSMDepthStencilAlpha.glDepthMask(memGetInt(ptr) != 0);
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.FRONT_FACE -> {
|
||||
GLStateManager.glFrontFace(memGetInt(ptr));
|
||||
GLSMRasterizer.glFrontFace(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
@@ -136,43 +149,43 @@ public final class CommandBufferExecutor {
|
||||
final int target = memGetInt(ptr);
|
||||
final int texture = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glBindTexture(target, texture);
|
||||
GLSMTextures.glBindTexture(target, texture);
|
||||
}
|
||||
case GLCommand.POLYGON_MODE -> {
|
||||
final int face = memGetInt(ptr);
|
||||
final int mode = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glPolygonMode(face, mode);
|
||||
GLSMRasterizer.glPolygonMode(face, mode);
|
||||
}
|
||||
case GLCommand.COLOR_MATERIAL -> {
|
||||
final int face = memGetInt(ptr);
|
||||
final int mode = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glColorMaterial(face, mode);
|
||||
GLSMLighting.glColorMaterial(face, mode);
|
||||
}
|
||||
case GLCommand.LINE_STIPPLE -> {
|
||||
final int factor = memGetInt(ptr);
|
||||
final int pattern = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glLineStipple(factor, (short) pattern);
|
||||
GLSMRasterizer.glLineStipple(factor, (short) pattern);
|
||||
}
|
||||
case GLCommand.STENCIL_MASK_SEPARATE -> {
|
||||
final int face = memGetInt(ptr);
|
||||
final int mask = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glStencilMaskSeparate(face, mask);
|
||||
GLSMDepthStencilAlpha.glStencilMaskSeparate(face, mask);
|
||||
}
|
||||
case GLCommand.FOGI -> {
|
||||
final int pname = memGetInt(ptr);
|
||||
final int param = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glFogi(pname, param);
|
||||
GLSMFog.glFogi(pname, param);
|
||||
}
|
||||
case GLCommand.HINT -> {
|
||||
final int target = memGetInt(ptr);
|
||||
final int mode = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glHint(target, mode);
|
||||
GLSMRasterizer.glHint(target, mode);
|
||||
}
|
||||
|
||||
// === Three int commands ===
|
||||
@@ -181,21 +194,21 @@ public final class CommandBufferExecutor {
|
||||
final int ref = memGetInt(ptr + 4);
|
||||
final int mask = memGetInt(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glStencilFunc(func, ref, mask);
|
||||
GLSMDepthStencilAlpha.glStencilFunc(func, ref, mask);
|
||||
}
|
||||
case GLCommand.STENCIL_OP -> {
|
||||
final int fail = memGetInt(ptr);
|
||||
final int zfail = memGetInt(ptr + 4);
|
||||
final int zpass = memGetInt(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glStencilOp(fail, zfail, zpass);
|
||||
GLSMDepthStencilAlpha.glStencilOp(fail, zfail, zpass);
|
||||
}
|
||||
case GLCommand.TEX_PARAMETERI -> {
|
||||
final int target = memGetInt(ptr);
|
||||
final int pname = memGetInt(ptr + 4);
|
||||
final int param = memGetInt(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glTexParameteri(target, pname, param);
|
||||
GLSMTextures.glTexParameteri(target, pname, param);
|
||||
}
|
||||
|
||||
// === Four int commands ===
|
||||
@@ -205,7 +218,7 @@ public final class CommandBufferExecutor {
|
||||
final int width = memGetInt(ptr + 8);
|
||||
final int height = memGetInt(ptr + 12);
|
||||
ptr += 16;
|
||||
GLStateManager.glViewport(x, y, width, height);
|
||||
GLSMRasterizer.glViewport(x, y, width, height);
|
||||
}
|
||||
case GLCommand.SCISSOR -> {
|
||||
final int x = memGetInt(ptr);
|
||||
@@ -213,7 +226,7 @@ public final class CommandBufferExecutor {
|
||||
final int width = memGetInt(ptr + 8);
|
||||
final int height = memGetInt(ptr + 12);
|
||||
ptr += 16;
|
||||
GLStateManager.glScissor(x, y, width, height);
|
||||
GLSMRasterizer.glScissor(x, y, width, height);
|
||||
}
|
||||
case GLCommand.BLEND_FUNC -> {
|
||||
final int srcRgb = memGetInt(ptr);
|
||||
@@ -222,9 +235,9 @@ public final class CommandBufferExecutor {
|
||||
final int dstAlpha = memGetInt(ptr + 12);
|
||||
ptr += 16;
|
||||
if (srcRgb == srcAlpha && dstRgb == dstAlpha) {
|
||||
GLStateManager.glBlendFunc(srcRgb, dstRgb);
|
||||
GLSMBlend.glBlendFunc(srcRgb, dstRgb);
|
||||
} else {
|
||||
GLStateManager.tryBlendFuncSeparate(srcRgb, dstRgb, srcAlpha, dstAlpha);
|
||||
GLSMBlend.tryBlendFuncSeparate(srcRgb, dstRgb, srcAlpha, dstAlpha);
|
||||
}
|
||||
}
|
||||
case GLCommand.COLOR_MASK -> {
|
||||
@@ -233,7 +246,7 @@ public final class CommandBufferExecutor {
|
||||
final boolean b = memGetInt(ptr + 8) != 0;
|
||||
final boolean a = memGetInt(ptr + 12) != 0;
|
||||
ptr += 16;
|
||||
GLStateManager.glColorMask(r, g, b, a);
|
||||
GLSMBlend.glColorMask(r, g, b, a);
|
||||
}
|
||||
case GLCommand.STENCIL_FUNC_SEPARATE -> {
|
||||
final int face = memGetInt(ptr);
|
||||
@@ -241,7 +254,7 @@ public final class CommandBufferExecutor {
|
||||
final int ref = memGetInt(ptr + 8);
|
||||
final int mask = memGetInt(ptr + 12);
|
||||
ptr += 16;
|
||||
GLStateManager.glStencilFuncSeparate(face, func, ref, mask);
|
||||
GLSMDepthStencilAlpha.glStencilFuncSeparate(face, func, ref, mask);
|
||||
}
|
||||
case GLCommand.STENCIL_OP_SEPARATE -> {
|
||||
final int face = memGetInt(ptr);
|
||||
@@ -249,28 +262,28 @@ public final class CommandBufferExecutor {
|
||||
final int dpfail = memGetInt(ptr + 8);
|
||||
final int dppass = memGetInt(ptr + 12);
|
||||
ptr += 16;
|
||||
GLStateManager.glStencilOpSeparate(face, sfail, dpfail, dppass);
|
||||
GLSMDepthStencilAlpha.glStencilOpSeparate(face, sfail, dpfail, dppass);
|
||||
}
|
||||
|
||||
// === Float commands ===
|
||||
case GLCommand.VERTEX_ATTRIB -> {
|
||||
GLStateManager.glVertexAttrib4f(memGetInt(ptr), memGetFloat(ptr + 4), memGetFloat(ptr + 8),
|
||||
GLSMCurrentAttribs.glVertexAttrib4f(memGetInt(ptr), memGetFloat(ptr + 4), memGetFloat(ptr + 8),
|
||||
memGetFloat(ptr + 12), memGetFloat(ptr + 16));
|
||||
ptr += 20;
|
||||
}
|
||||
case GLCommand.POINT_SIZE -> {
|
||||
GLStateManager.glPointSize(memGetFloat(ptr));
|
||||
GLSMRasterizer.glPointSize(memGetFloat(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.LINE_WIDTH -> {
|
||||
GLStateManager.glLineWidth(memGetFloat(ptr));
|
||||
GLSMRasterizer.glLineWidth(memGetFloat(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.POLYGON_OFFSET -> {
|
||||
final float factor = memGetFloat(ptr);
|
||||
final float units = memGetFloat(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glPolygonOffset(factor, units);
|
||||
GLSMRasterizer.glPolygonOffset(factor, units);
|
||||
}
|
||||
case GLCommand.COLOR -> {
|
||||
final float r = memGetFloat(ptr);
|
||||
@@ -278,14 +291,14 @@ public final class CommandBufferExecutor {
|
||||
final float b = memGetFloat(ptr + 8);
|
||||
final float a = memGetFloat(ptr + 12);
|
||||
ptr += 16;
|
||||
GLStateManager.glColor4f(r, g, b, a);
|
||||
GLSMCurrentAttribs.glColor4f(r, g, b, a);
|
||||
}
|
||||
case GLCommand.SECONDARY_COLOR -> {
|
||||
final float r = memGetFloat(ptr);
|
||||
final float g = memGetFloat(ptr + 4);
|
||||
final float b = memGetFloat(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glSecondaryColor3f(r, g, b);
|
||||
GLSMCurrentAttribs.glSecondaryColor3f(r, g, b);
|
||||
}
|
||||
case GLCommand.CLEAR_COLOR -> {
|
||||
final float r = memGetFloat(ptr);
|
||||
@@ -293,12 +306,12 @@ public final class CommandBufferExecutor {
|
||||
final float b = memGetFloat(ptr + 8);
|
||||
final float a = memGetFloat(ptr + 12);
|
||||
ptr += 16;
|
||||
GLStateManager.glClearColor(r, g, b, a);
|
||||
GLSMBlend.glClearColor(r, g, b, a);
|
||||
}
|
||||
case GLCommand.CLEAR_DEPTH -> {
|
||||
final double depth = memGetDouble(ptr);
|
||||
ptr += 8;
|
||||
GLStateManager.glClearDepth(depth);
|
||||
GLSMDepthStencilAlpha.glClearDepth(depth);
|
||||
}
|
||||
case GLCommand.BLEND_COLOR -> {
|
||||
final float r = memGetFloat(ptr);
|
||||
@@ -306,7 +319,7 @@ public final class CommandBufferExecutor {
|
||||
final float b = memGetFloat(ptr + 8);
|
||||
final float a = memGetFloat(ptr + 12);
|
||||
ptr += 16;
|
||||
GLStateManager.glBlendColor(r, g, b, a);
|
||||
GLSMBlend.glBlendColor(r, g, b, a);
|
||||
}
|
||||
|
||||
// === Mixed int+float commands ===
|
||||
@@ -314,53 +327,53 @@ public final class CommandBufferExecutor {
|
||||
final int func = memGetInt(ptr);
|
||||
final float ref = memGetFloat(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glAlphaFunc(func, ref);
|
||||
GLSMDepthStencilAlpha.glAlphaFunc(func, ref);
|
||||
}
|
||||
case GLCommand.FOGF -> {
|
||||
final int pname = memGetInt(ptr);
|
||||
final float param = memGetFloat(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glFogf(pname, param);
|
||||
GLSMFog.glFogf(pname, param);
|
||||
}
|
||||
case GLCommand.LIGHTF -> {
|
||||
final int light = memGetInt(ptr);
|
||||
final int pname = memGetInt(ptr + 4);
|
||||
final float param = memGetFloat(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glLightf(light, pname, param);
|
||||
GLSMLighting.glLightf(light, pname, param);
|
||||
}
|
||||
case GLCommand.LIGHT_MODELF -> {
|
||||
final int pname = memGetInt(ptr);
|
||||
final float param = memGetFloat(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glLightModelf(pname, param);
|
||||
GLSMLighting.glLightModelf(pname, param);
|
||||
}
|
||||
case GLCommand.LIGHTI -> {
|
||||
final int light = memGetInt(ptr);
|
||||
final int pname = memGetInt(ptr + 4);
|
||||
final int param = memGetInt(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glLighti(light, pname, param);
|
||||
GLSMLighting.glLighti(light, pname, param);
|
||||
}
|
||||
case GLCommand.LIGHT_MODELI -> {
|
||||
final int pname = memGetInt(ptr);
|
||||
final int param = memGetInt(ptr + 4);
|
||||
ptr += 8;
|
||||
GLStateManager.glLightModeli(pname, param);
|
||||
GLSMLighting.glLightModeli(pname, param);
|
||||
}
|
||||
case GLCommand.MATERIALF -> {
|
||||
final int face = memGetInt(ptr);
|
||||
final int pname = memGetInt(ptr + 4);
|
||||
final float param = memGetFloat(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glMaterialf(face, pname, param);
|
||||
GLSMLighting.glMaterialf(face, pname, param);
|
||||
}
|
||||
case GLCommand.TEX_PARAMETERF -> {
|
||||
final int target = memGetInt(ptr);
|
||||
final int pname = memGetInt(ptr + 4);
|
||||
final float param = memGetFloat(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glTexParameterf(target, pname, param);
|
||||
GLSMTextures.glTexParameterf(target, pname, param);
|
||||
}
|
||||
|
||||
// === Matrix commands ===
|
||||
@@ -372,21 +385,21 @@ public final class CommandBufferExecutor {
|
||||
ptr += 4;
|
||||
}
|
||||
MATRIX_BUFFER.flip();
|
||||
GLStateManager.glMultMatrix(MATRIX_BUFFER);
|
||||
GLSMMatrices.glMultMatrix(MATRIX_BUFFER);
|
||||
}
|
||||
case GLCommand.TRANSLATE -> {
|
||||
final float x = memGetFloat(ptr);
|
||||
final float y = memGetFloat(ptr + 4);
|
||||
final float z = memGetFloat(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glTranslatef(x, y, z);
|
||||
GLSMMatrices.glTranslatef(x, y, z);
|
||||
}
|
||||
case GLCommand.SCALE -> {
|
||||
final float x = memGetFloat(ptr);
|
||||
final float y = memGetFloat(ptr + 4);
|
||||
final float z = memGetFloat(ptr + 8);
|
||||
ptr += 12;
|
||||
GLStateManager.glScalef(x, y, z);
|
||||
GLSMMatrices.glScalef(x, y, z);
|
||||
}
|
||||
case GLCommand.LOAD_MATRIX -> {
|
||||
MATRIX_BUFFER.clear();
|
||||
@@ -395,7 +408,7 @@ public final class CommandBufferExecutor {
|
||||
ptr += 4;
|
||||
}
|
||||
MATRIX_BUFFER.flip();
|
||||
GLStateManager.glLoadMatrix(MATRIX_BUFFER);
|
||||
GLSMMatrices.glLoadMatrix(MATRIX_BUFFER);
|
||||
}
|
||||
|
||||
// === Buffer commands ===
|
||||
@@ -409,7 +422,7 @@ public final class CommandBufferExecutor {
|
||||
ptr += 4;
|
||||
}
|
||||
PARAMS_BUFFER.flip();
|
||||
GLStateManager.glFog(pname, PARAMS_BUFFER);
|
||||
GLSMFog.glFog(pname, PARAMS_BUFFER);
|
||||
}
|
||||
case GLCommand.LIGHT -> {
|
||||
final int light = memGetInt(ptr);
|
||||
@@ -422,7 +435,7 @@ public final class CommandBufferExecutor {
|
||||
ptr += 4;
|
||||
}
|
||||
PARAMS_BUFFER.flip();
|
||||
GLStateManager.glLight(light, pname, PARAMS_BUFFER);
|
||||
GLSMLighting.glLight(light, pname, PARAMS_BUFFER);
|
||||
}
|
||||
case GLCommand.LIGHT_MODEL -> {
|
||||
final int pname = memGetInt(ptr);
|
||||
@@ -434,7 +447,7 @@ public final class CommandBufferExecutor {
|
||||
ptr += 4;
|
||||
}
|
||||
PARAMS_BUFFER.flip();
|
||||
GLStateManager.glLightModel(pname, PARAMS_BUFFER);
|
||||
GLSMLighting.glLightModel(pname, PARAMS_BUFFER);
|
||||
}
|
||||
case GLCommand.MATERIAL -> {
|
||||
final int face = memGetInt(ptr);
|
||||
@@ -447,7 +460,7 @@ public final class CommandBufferExecutor {
|
||||
ptr += 4;
|
||||
}
|
||||
PARAMS_BUFFER.flip();
|
||||
GLStateManager.glMaterial(face, pname, PARAMS_BUFFER);
|
||||
GLSMLighting.glMaterial(face, pname, PARAMS_BUFFER);
|
||||
}
|
||||
|
||||
case GLCommand.CLIP_PLANE -> {
|
||||
@@ -460,7 +473,7 @@ public final class CommandBufferExecutor {
|
||||
PARAMS_DOUBLE_BUFFER.clear();
|
||||
PARAMS_DOUBLE_BUFFER.put(a).put(b).put(c).put(d);
|
||||
PARAMS_DOUBLE_BUFFER.flip();
|
||||
GLStateManager.glClipPlane(plane, PARAMS_DOUBLE_BUFFER);
|
||||
GLSMRasterizer.glClipPlane(plane, PARAMS_DOUBLE_BUFFER);
|
||||
}
|
||||
|
||||
// === Draw commands ===
|
||||
@@ -484,19 +497,19 @@ public final class CommandBufferExecutor {
|
||||
final byte b = (byte) ((color >> 16) & 0xFF);
|
||||
final byte g = (byte) ((color >> 8) & 0xFF);
|
||||
final byte r = (byte) ((color & 0xFF));
|
||||
GLStateManager.glColor4ub(r, g, b, a);
|
||||
GLSMCurrentAttribs.glColor4ub(r, g, b, a);
|
||||
}
|
||||
if ((flags & VertexFlags.NORMAL_BIT) != 0) {
|
||||
final int normal = memGetInt(ptr + 12);
|
||||
float nx = (byte)(normal) / 127.0f;
|
||||
float ny = (byte)(normal >> 8) / 127.0f;
|
||||
float nz = (byte)(normal >> 16) / 127.0f;
|
||||
GLStateManager.glNormal3f(nx, ny, nz);
|
||||
GLSMCurrentAttribs.glNormal3f(nx, ny, nz);
|
||||
}
|
||||
if ((flags & VertexFlags.TEXTURE_BIT) != 0) {
|
||||
final float s = memGetFloat(ptr + 16);
|
||||
final float t = memGetFloat(ptr + 20);
|
||||
GLStateManager.glTexCoord2f(s, t);
|
||||
GLSMCurrentAttribs.glTexCoord2f(s, t);
|
||||
}
|
||||
ptr += 24; // Skip full command size (28 - 4 for cmd already read)
|
||||
}
|
||||
@@ -506,7 +519,7 @@ public final class CommandBufferExecutor {
|
||||
DisplayListManager.glCallList(listId);
|
||||
}
|
||||
case GLCommand.DRAW_BUFFER -> {
|
||||
GLStateManager.glDrawBuffer(memGetInt(ptr));
|
||||
GLSMFramebuffer.glDrawBuffer(memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.DRAW_BUFFERS -> {
|
||||
@@ -518,16 +531,16 @@ public final class CommandBufferExecutor {
|
||||
}
|
||||
DRAW_BUFFERS_BUFFER.flip();
|
||||
ptr += 4 * MAX_DRAW_BUFFERS;
|
||||
GLStateManager.glDrawBuffers(DRAW_BUFFERS_BUFFER);
|
||||
GLSMFramebuffer.glDrawBuffers(DRAW_BUFFERS_BUFFER);
|
||||
}
|
||||
case GLCommand.BIND_VBO -> {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, memGetInt(ptr));
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, memGetInt(ptr));
|
||||
ptr += 4;
|
||||
}
|
||||
case GLCommand.BIND_VAO -> {
|
||||
final int vao = memGetInt(ptr);
|
||||
ptr += 4;
|
||||
if (compiledDisplayList.replaysVertexArrayBind(vao)) GLStateManager.glBindVertexArray(vao);
|
||||
if (compiledDisplayList.replaysVertexArrayBind(vao)) GLSMVertexInput.glBindVertexArray(vao);
|
||||
}
|
||||
|
||||
// === Complex object reference ===
|
||||
|
||||
+4
-3
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.glsm.recording;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMPrograms;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.commands.DisplayListCommand;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.commands.IndexedDrawBatch;
|
||||
@@ -43,15 +44,15 @@ public final class CompiledDisplayList {
|
||||
|
||||
int resolveProgram(int program) {
|
||||
if (program == 0) return 0;
|
||||
final long generation = GLStateManager.getProgramLifetimeGeneration();
|
||||
final long generation = GLSMPrograms.getProgramLifetimeGeneration();
|
||||
if (replayPrograms == null) replayPrograms = new Int2IntOpenHashMap();
|
||||
if (programLifetimeGeneration != generation) {
|
||||
replayPrograms.clear();
|
||||
programLifetimeGeneration = generation;
|
||||
}
|
||||
if (replayPrograms.containsKey(program)) return replayPrograms.get(program);
|
||||
final boolean valid = GLStateManager.glIsProgram(program);
|
||||
if (!valid || !GLStateManager.isProgramPendingDeletion(program)) {
|
||||
final boolean valid = GLSMPrograms.glIsProgram(program);
|
||||
if (!valid || !GLSMPrograms.isProgramPendingDeletion(program)) {
|
||||
replayPrograms.put(program, valid ? program : 0);
|
||||
}
|
||||
return valid ? program : 0;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.IVertexArrayObject;
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMDraws;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.ImmediateExtendedAttribHandler;
|
||||
import com.gtnewhorizons.angelica.glsm.streaming.LineQuads;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -33,7 +34,7 @@ public final class DisplayListVBO {
|
||||
}
|
||||
if (extVbos != null) {
|
||||
for (int extVbo : extVbos) {
|
||||
if (extVbo != 0) GLStateManager.glDeleteBuffers(extVbo);
|
||||
if (extVbo != 0) GLSMBuffers.glDeleteBuffers(extVbo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,41 +100,42 @@ public final class DisplayListVBO {
|
||||
|
||||
public void render() {
|
||||
if (vao == null) return;
|
||||
if (lineQuads != null && GLStateManager.ffpWidensLineQuads()) {
|
||||
renderLineQuads();
|
||||
return;
|
||||
}
|
||||
vao.bind();
|
||||
if (pendingExtVbo != 0) {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, pendingExtVbo);
|
||||
ImmediateExtendedAttribHandler.setupExtAttribPointers(0L, ImmediateExtendedAttribHandler.EXT_STRIDE);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
pendingExtVbo = 0;
|
||||
}
|
||||
if (count <= 0) { vao.unbind(); return; }
|
||||
VAOManager.setCurrentVertexFlags(vertexFlags);
|
||||
FfpExtendedAttribs.beginInternalDraw();
|
||||
final int prevVAO = GLSMVertexInput.getBoundVAO();
|
||||
try {
|
||||
vao.draw(drawMode, start, count);
|
||||
if (lineQuads != null && GLSMDraws.ffpWidensLineQuads()) {
|
||||
renderLineQuads();
|
||||
return;
|
||||
}
|
||||
vao.bind();
|
||||
if (pendingExtVbo != 0) {
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, pendingExtVbo);
|
||||
ImmediateExtendedAttribHandler.setupExtAttribPointers(0L, ImmediateExtendedAttribHandler.EXT_STRIDE);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
pendingExtVbo = 0;
|
||||
}
|
||||
if (count <= 0) { vao.unbind(); return; }
|
||||
VAOManager.setCurrentVertexFlags(vertexFlags);
|
||||
FfpExtendedAttribs.beginInternalDraw();
|
||||
try {
|
||||
vao.draw(drawMode, start, count);
|
||||
} finally {
|
||||
FfpExtendedAttribs.endInternalDraw();
|
||||
}
|
||||
vao.unbind();
|
||||
} finally {
|
||||
FfpExtendedAttribs.endInternalDraw();
|
||||
GLSMVertexInput.glBindVertexArray(prevVAO);
|
||||
}
|
||||
vao.unbind();
|
||||
}
|
||||
|
||||
private void renderLineQuads() {
|
||||
final GLContextState glCtx = GLStateManager.ctx();
|
||||
lineQuads.bind();
|
||||
VAOManager.setCurrentVertexFlags(lineQuadFlags);
|
||||
final boolean culled = LineQuads.disableCulling();
|
||||
glCtx.lineQuadsActive = true;
|
||||
final boolean culled = LineQuads.beginDraw(lineQuadFlags);
|
||||
FfpExtendedAttribs.beginInternalDraw();
|
||||
try {
|
||||
lineQuads.draw(GL11.GL_TRIANGLES, lineQuadStart, lineQuadCount);
|
||||
} finally {
|
||||
FfpExtendedAttribs.endInternalDraw();
|
||||
glCtx.lineQuadsActive = false;
|
||||
LineQuads.restoreCulling(culled);
|
||||
LineQuads.endDraw(culled);
|
||||
}
|
||||
lineQuads.unbind();
|
||||
}
|
||||
|
||||
+7
-5
@@ -9,6 +9,8 @@ import com.gtnewhorizon.gtnhlib.client.renderer.vbo.IVertexBuffer;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMRasterizer;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMHooks;
|
||||
@@ -80,7 +82,7 @@ public final class DisplayListVBOBuilder {
|
||||
final IntArrayList extCounts = wantExt ? new IntArrayList() : null;
|
||||
final IntArrayList extPrims = wantExt ? new IntArrayList() : null;
|
||||
// drawIndex, start, vertexCount, drawMode for each line draw
|
||||
final IntArrayList lineDraws = GLStateManager.wideLineEmulationEnabled ? new IntArrayList() : null;
|
||||
final IntArrayList lineDraws = GLSMRasterizer.wideLineEmulationEnabled ? new IntArrayList() : null;
|
||||
|
||||
for (FormatData data : formatData) {
|
||||
int vertexCount;
|
||||
@@ -212,11 +214,11 @@ public final class DisplayListVBOBuilder {
|
||||
extAddr + (long) rStart * extStride, extStride);
|
||||
}
|
||||
|
||||
final int extVbo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, extVbo);
|
||||
final int extVbo = GLSMBuffers.glGenBuffers();
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, extVbo);
|
||||
ext.position(0).limit(extVerts * extStride);
|
||||
GLStateManager.glBufferData(GL15.GL_ARRAY_BUFFER, ext, GL15.GL_STATIC_DRAW);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLSMBuffers.glBufferData(GL15.GL_ARRAY_BUFFER, ext, GL15.GL_STATIC_DRAW);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
memFree(ext);
|
||||
return extVbo;
|
||||
}
|
||||
|
||||
+3
-2
@@ -4,6 +4,7 @@ import com.gtnewhorizon.gtnhlib.client.renderer.CallbackTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMCurrentAttribs;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLTypes;
|
||||
import com.gtnewhorizons.angelica.glsm.QuadConverter;
|
||||
@@ -77,7 +78,7 @@ public final class ImmediateModeRecorder {
|
||||
|
||||
/**
|
||||
* Set the current lightmap coordinate as packed brightness.
|
||||
* Called by GLStateManager.glMultiTexCoord2f for unit 1 during recording/drawing.
|
||||
* Called by GLSMCurrentAttribs.glMultiTexCoord2f for unit 1 during recording/drawing.
|
||||
*/
|
||||
public static void setLightmapCoord(float s, float t) {
|
||||
tessellator().setBrightness(((int) t << 16) | ((int) s & 0xFFFF));
|
||||
@@ -119,7 +120,7 @@ public final class ImmediateModeRecorder {
|
||||
final DirectTessellator t = tessellator();
|
||||
t.reset();
|
||||
t.startDrawing(primitiveType);
|
||||
final var c = GLStateManager.getColor();
|
||||
final var c = GLSMCurrentAttribs.getColor();
|
||||
t.setColorRGBA((int) (c.getRed() * 255.0f), (int) (c.getGreen() * 255.0f), (int) (c.getBlue() * 255.0f), (int) (c.getAlpha() * 255.0f));
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMDraws;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
|
||||
public final class BatchedIndexedDrawCmd implements DisplayListCommand {
|
||||
private IndexedDrawBatch batch;
|
||||
@@ -25,8 +26,13 @@ public final class BatchedIndexedDrawCmd implements DisplayListCommand {
|
||||
@Override
|
||||
public void execute() {
|
||||
if (batch == null) return;
|
||||
batch.bind();
|
||||
GLStateManager.glDrawElements(drawMode, indexCount, indexType, indexByteOffset);
|
||||
final int prevVAO = GLSMVertexInput.getBoundVAO();
|
||||
try {
|
||||
batch.bind();
|
||||
GLSMDraws.glDrawElements(drawMode, indexCount, indexType, indexByteOffset);
|
||||
} finally {
|
||||
GLSMVertexInput.glBindVertexArray(prevVAO);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+29
-12
@@ -1,7 +1,12 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.GLContextState;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
|
||||
public final class IndexedDrawBatch {
|
||||
@@ -24,31 +29,43 @@ public final class IndexedDrawBatch {
|
||||
public void bind() {
|
||||
final GLContextState glCtx = GLStateManager.ctx();
|
||||
if (vaoCtx == glCtx) {
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLSMVertexInput.glBindVertexArray(vao);
|
||||
return;
|
||||
}
|
||||
final int prevVBO = GLStateManager.getBoundVBO();
|
||||
final int v = GLStateManager.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(v);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, sharedVBO);
|
||||
final int prevVBO = GLSMBuffers.getBoundVBO();
|
||||
final int v = GLSMVertexInput.glGenVertexArrays();
|
||||
GLSMVertexInput.glBindVertexArray(v);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, sharedVBO);
|
||||
final int stride = layout.stride();
|
||||
int vertexFlags = 0;
|
||||
for (int i = 0; i < layout.locations.length; i++) {
|
||||
final int loc = layout.locations[i];
|
||||
GLStateManager.glVertexAttribPointer(loc, layout.sizes[i], layout.types[i], layout.normalized[i], stride, layout.offset(i));
|
||||
GLStateManager.glEnableVertexAttribArray(loc);
|
||||
GLSMVertexInput.glVertexAttribPointer(loc, layout.sizes[i], layout.types[i], layout.normalized[i], stride, layout.offset(i));
|
||||
GLSMVertexInput.glEnableVertexAttribArray(loc);
|
||||
vertexFlags |= vertexFlag(loc);
|
||||
}
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, sharedEBO);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, prevVBO);
|
||||
// glVertexAttribPointer doesn't set these, and the FFP shader only reads the inputs they name. Saved with the VAO.
|
||||
VAOManager.setCurrentVertexFlags(vertexFlags);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, sharedEBO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, prevVBO);
|
||||
vao = v;
|
||||
vaoCtx = glCtx;
|
||||
}
|
||||
|
||||
private static int vertexFlag(int location) {
|
||||
if (location == Usage.COLOR.getAttributeLocation()) return VertexFlags.COLOR_BIT;
|
||||
if (location == Usage.NORMAL.getAttributeLocation()) return VertexFlags.NORMAL_BIT;
|
||||
if (location == Usage.PRIMARY_UV.getAttributeLocation()) return VertexFlags.TEXTURE_BIT;
|
||||
if (location == Usage.SECONDARY_UV.getAttributeLocation()) return VertexFlags.BRIGHTNESS_BIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void delete() {
|
||||
if (deleted) return;
|
||||
deleted = true;
|
||||
if (vaoCtx == GLStateManager.ctx()) GLStateManager.glDeleteVertexArrays(vao);
|
||||
if (sharedVBO != 0) GLStateManager.glDeleteBuffers(sharedVBO);
|
||||
if (sharedEBO != 0) GLStateManager.glDeleteBuffers(sharedEBO);
|
||||
if (vaoCtx == GLStateManager.ctx()) GLSMVertexInput.glDeleteVertexArrays(vao);
|
||||
if (sharedVBO != 0) GLSMBuffers.glDeleteBuffers(sharedVBO);
|
||||
if (sharedEBO != 0) GLSMBuffers.glDeleteBuffers(sharedEBO);
|
||||
vao = sharedVBO = sharedEBO = 0;
|
||||
vaoCtx = null;
|
||||
}
|
||||
|
||||
+15
-14
@@ -1,7 +1,8 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMBuffers;
|
||||
import com.gtnewhorizons.angelica.glsm.GLSMVertexInput;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
@@ -35,8 +36,8 @@ public final class IndexedDrawBatchBuilder {
|
||||
final List<IndexedDrawBatch> out = new ArrayList<>();
|
||||
if (captures.isEmpty()) return out;
|
||||
|
||||
final int prevVBO = GLStateManager.getBoundVBO();
|
||||
final int prevEBO = GLStateManager.getBoundEBO();
|
||||
final int prevVBO = GLSMBuffers.getBoundVBO();
|
||||
final int prevEBO = GLSMVertexInput.getBoundEBO();
|
||||
|
||||
final List<GroupResult> results = new ArrayList<>();
|
||||
boolean success = false;
|
||||
@@ -57,8 +58,8 @@ public final class IndexedDrawBatchBuilder {
|
||||
if (!success) {
|
||||
for (GroupResult r : results) r.batch.delete();
|
||||
}
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, prevEBO);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, prevVBO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, prevEBO);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, prevVBO);
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -95,12 +96,12 @@ public final class IndexedDrawBatchBuilder {
|
||||
final long[] indexOffsets = new long[n];
|
||||
|
||||
try {
|
||||
sharedVBO = GLStateManager.glGenBuffers();
|
||||
sharedEBO = GLStateManager.glGenBuffers();
|
||||
sharedVBO = GLSMBuffers.glGenBuffers();
|
||||
sharedEBO = GLSMBuffers.glGenBuffers();
|
||||
eboData = MemoryUtilities.memAlloc((int) totalIndexBytes);
|
||||
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, sharedVBO);
|
||||
GLStateManager.glBufferData(GL15.GL_ARRAY_BUFFER, totalVertexBytes, GL15.GL_STATIC_DRAW);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ARRAY_BUFFER, sharedVBO);
|
||||
GLSMBuffers.glBufferData(GL15.GL_ARRAY_BUFFER, totalVertexBytes, GL15.GL_STATIC_DRAW);
|
||||
|
||||
int vboBytePos = 0;
|
||||
int eboBytePos = 0;
|
||||
@@ -110,7 +111,7 @@ public final class IndexedDrawBatchBuilder {
|
||||
for (int g = 0; g < n; g++) {
|
||||
final IndexedDrawCapture c = group.get(g);
|
||||
final int vBytes = c.vertexCount * c.layoutKey.stride();
|
||||
GLStateManager.glBufferSubData(GL15.GL_ARRAY_BUFFER, vboBytePos, c.vertexData);
|
||||
GLSMBuffers.glBufferSubData(GL15.GL_ARRAY_BUFFER, vboBytePos, c.vertexData);
|
||||
|
||||
final long srcIdxAddr = memAddress0(c.indexData);
|
||||
final int idxBytes = c.indexCount * 4;
|
||||
@@ -137,8 +138,8 @@ public final class IndexedDrawBatchBuilder {
|
||||
|
||||
eboData.position(0).limit((int) totalIndexBytes);
|
||||
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, sharedEBO);
|
||||
GLStateManager.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, eboData, GL15.GL_STATIC_DRAW);
|
||||
GLSMBuffers.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, sharedEBO);
|
||||
GLSMBuffers.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, eboData, GL15.GL_STATIC_DRAW);
|
||||
|
||||
success = true;
|
||||
return new GroupResult(new IndexedDrawBatch(group.get(0).layoutKey, sharedVBO, sharedEBO),
|
||||
@@ -146,8 +147,8 @@ public final class IndexedDrawBatchBuilder {
|
||||
} finally {
|
||||
if (eboData != null) MemoryUtilities.memFree(eboData);
|
||||
if (!success) {
|
||||
if (sharedVBO != 0) GLStateManager.glDeleteBuffers(sharedVBO);
|
||||
if (sharedEBO != 0) GLStateManager.glDeleteBuffers(sharedEBO);
|
||||
if (sharedVBO != 0) GLSMBuffers.glDeleteBuffers(sharedVBO);
|
||||
if (sharedEBO != 0) GLSMBuffers.glDeleteBuffers(sharedEBO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loaded 100 of 938 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user