Very experimental rendering subsystem changes
This commit is contained in:
parent
45ec057457
commit
c89e65882c
12 changed files with 997 additions and 228 deletions
|
@ -21,25 +21,30 @@ package de.staropensource.engine.rendering;
|
||||||
|
|
||||||
import de.staropensource.engine.base.annotation.EngineSubsystem;
|
import de.staropensource.engine.base.annotation.EngineSubsystem;
|
||||||
import de.staropensource.engine.base.annotation.EventListener;
|
import de.staropensource.engine.base.annotation.EventListener;
|
||||||
|
import de.staropensource.engine.base.implementable.Event;
|
||||||
import de.staropensource.engine.base.implementable.SubsystemClass;
|
import de.staropensource.engine.base.implementable.SubsystemClass;
|
||||||
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
||||||
import de.staropensource.engine.base.logging.Logger;
|
import de.staropensource.engine.base.logging.Logger;
|
||||||
import de.staropensource.engine.base.type.EventPriority;
|
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||||
import de.staropensource.engine.base.utility.Math;
|
|
||||||
import de.staropensource.engine.base.utility.information.EngineInformation;
|
import de.staropensource.engine.base.utility.information.EngineInformation;
|
||||||
import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem;
|
import de.staropensource.engine.base.implementation.versioning.StarOpenSourceVersioningSystem;
|
||||||
import de.staropensource.engine.base.event.InternalEngineShutdownEvent;
|
import de.staropensource.engine.base.event.InternalEngineShutdownEvent;
|
||||||
import de.staropensource.engine.base.type.DependencyVector;
|
import de.staropensource.engine.base.type.DependencyVector;
|
||||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
||||||
import de.staropensource.engine.rendering.event.InputEvent;
|
import de.staropensource.engine.rendering.event.InputEvent;
|
||||||
import de.staropensource.engine.rendering.event.RenderingErrorEvent;
|
import de.staropensource.engine.rendering.event.RenderingErrorEvent;
|
||||||
import de.staropensource.engine.rendering.exception.NotOnMainThreadException;
|
import de.staropensource.engine.rendering.exception.NotOnMainThreadException;
|
||||||
|
import de.staropensource.engine.rendering.renderer.Renderer;
|
||||||
import de.staropensource.engine.rendering.type.Window;
|
import de.staropensource.engine.rendering.type.Window;
|
||||||
|
import de.staropensource.engine.rendering.type.window.RenderingPlatform;
|
||||||
import de.staropensource.engine.rendering.type.window.VsyncMode;
|
import de.staropensource.engine.rendering.type.window.VsyncMode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.lwjgl.glfw.*;
|
import org.lwjgl.glfw.*;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
@ -117,8 +122,13 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
|
|
||||||
// Precompute event listeners
|
// Precompute event listeners
|
||||||
cacheEvents();
|
cacheEvents();
|
||||||
|
|
||||||
|
// Initialize GLFW
|
||||||
initGlfw();
|
initGlfw();
|
||||||
|
|
||||||
|
// Initialize renderer
|
||||||
|
Renderer.initialize();
|
||||||
|
|
||||||
// Warn about subsystem and API instability
|
// Warn about subsystem and API instability
|
||||||
Logger.warn("The rendering subsystem is experimental. Subsystem and API stability are not guaranteed.");
|
Logger.warn("The rendering subsystem is experimental. Subsystem and API stability are not guaranteed.");
|
||||||
}
|
}
|
||||||
|
@ -150,10 +160,10 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
Logger.diag("Setting initialization hints");
|
Logger.diag("Setting initialization hints");
|
||||||
switch (RenderingSubsystemConfiguration.getInstance().getInitialPlatform()) {
|
switch (RenderingSubsystemConfiguration.getInstance().getInitialPlatform()) {
|
||||||
case ANY -> glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
|
case ANY -> glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
|
||||||
case WAYLAND -> tryPlatform(GLFW_PLATFORM_WAYLAND);
|
case WAYLAND -> tryPlatform(GLFW_PLATFORM_WAYLAND, RenderingPlatform.WAYLAND);
|
||||||
case X11 -> tryPlatform(GLFW_PLATFORM_X11);
|
case X11 -> tryPlatform(GLFW_PLATFORM_X11, RenderingPlatform.X11);
|
||||||
case WIN32 -> tryPlatform(GLFW_PLATFORM_WIN32);
|
case WIN32 -> tryPlatform(GLFW_PLATFORM_WIN32, RenderingPlatform.WIN32);
|
||||||
case COCOA -> tryPlatform(GLFW_PLATFORM_COCOA);
|
case COCOA -> tryPlatform(GLFW_PLATFORM_COCOA, RenderingPlatform.COCOA);
|
||||||
case NONE -> glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_NULL);
|
case NONE -> glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_NULL);
|
||||||
}
|
}
|
||||||
glfwInitHint(GLFW_WAYLAND_LIBDECOR, RenderingSubsystemConfiguration.getInstance().isInitialDisableLibdecor() ? GLFW_WAYLAND_DISABLE_LIBDECOR : GLFW_WAYLAND_PREFER_LIBDECOR);
|
glfwInitHint(GLFW_WAYLAND_LIBDECOR, RenderingSubsystemConfiguration.getInstance().isInitialDisableLibdecor() ? GLFW_WAYLAND_DISABLE_LIBDECOR : GLFW_WAYLAND_PREFER_LIBDECOR);
|
||||||
|
@ -182,7 +192,7 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
|
|
||||||
long shutdownTime = Miscellaneous.measureExecutionTime(() -> {
|
long shutdownTime = Miscellaneous.measureExecutionTime(() -> {
|
||||||
// Close all windows
|
// Close all windows
|
||||||
for (Window window : Window.getWindows())
|
for (Window window : new ArrayList<>(Window.getWindows()))
|
||||||
window.close();
|
window.close();
|
||||||
|
|
||||||
instance.errorCallback.free();
|
instance.errorCallback.free();
|
||||||
|
@ -198,7 +208,7 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
* @see RenderingSubsystemConfiguration#errorRenderingFailures
|
* @see RenderingSubsystemConfiguration#errorRenderingFailures
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
@EventListener(event = RenderingErrorEvent.class, priority = EventPriority.EXCLUSIVELY_IMPORTANT)
|
@EventListener(event = RenderingErrorEvent.class, priority = Event.Priority.EXCLUSIVELY_IMPORTANT)
|
||||||
private static void logRenderingError(@NotNull String error) {
|
private static void logRenderingError(@NotNull String error) {
|
||||||
Logger.error("Rendering error occurred: " + error);
|
Logger.error("Rendering error occurred: " + error);
|
||||||
}
|
}
|
||||||
|
@ -220,6 +230,9 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
|
|
||||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>();
|
LinkedHashMap<@NotNull Window, @NotNull Throwable> throwables = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
// Poll for events
|
||||||
|
glfwPollEvents();
|
||||||
|
|
||||||
// Update and render all windows
|
// Update and render all windows
|
||||||
for (Window window : Window.getWindows()) {
|
for (Window window : Window.getWindows()) {
|
||||||
if (!window.isRendering())
|
if (!window.isRendering())
|
||||||
|
@ -232,14 +245,14 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
Logger.error("Rendering window " + window + " failed: Threw throwable " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage()));
|
Logger.error("Rendering window " + window + " failed: Threw throwable " + throwable.getClass().getName() + (throwable.getMessage() == null ? "" : ": " + throwable.getMessage()));
|
||||||
throwables.put(window, throwable);
|
throwables.put(window, throwable);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Poll for events
|
//bgfx_frame(false);
|
||||||
glfwPollEvents();
|
}
|
||||||
|
|
||||||
return throwables;
|
return throwables;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* Renders all windows continuously.
|
* Renders all windows continuously.
|
||||||
* To render all windows just once, invoke
|
* To render all windows just once, invoke
|
||||||
* {@link #renderWindows()} instead.
|
* {@link #renderWindows()} instead.
|
||||||
|
@ -270,6 +283,8 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
if (!RenderingSubsystemConfiguration.getInstance().isDebugFrames())
|
if (!RenderingSubsystemConfiguration.getInstance().isDebugFrames())
|
||||||
reportDuration = Long.MAX_VALUE;
|
reportDuration = Long.MAX_VALUE;
|
||||||
|
|
||||||
|
Logger.info("Entering render loop");
|
||||||
|
|
||||||
// Run while the 'output' is empty
|
// Run while the 'output' is empty
|
||||||
while (output.get().isEmpty()) {
|
while (output.get().isEmpty()) {
|
||||||
renderTime = Miscellaneous.measureExecutionTime(() -> {
|
renderTime = Miscellaneous.measureExecutionTime(() -> {
|
||||||
|
@ -293,11 +308,33 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
Thread.onSpinWait();
|
Thread.onSpinWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Calculate delta time and frame count every second
|
// Calculate delta time and frame count every second
|
||||||
if (System.currentTimeMillis() >= reportDuration) {
|
if (System.currentTimeMillis() >= reportDuration) {
|
||||||
deltaTime = Math.getMeanLong(splitDeltaTime); // Calculate delta time
|
deltaTime = NumberUtil.calculateMeanLong(splitDeltaTime); // Calculate delta time
|
||||||
Logger.diag("Delta time average: " + deltaTime + " | Frames/s: " + 1000 / deltaTime); // Print delta time and frame count to console
|
Logger.diag("Delta time average: " + deltaTime + " | Frames/s: " + 1000 / deltaTime); // Print delta time and frame count to console
|
||||||
|
|
||||||
|
if (RenderingSubsystemConfiguration.getInstance().isDebugWindowStates())
|
||||||
|
for (Window window : Window.getWindows())
|
||||||
|
Logger.diag(
|
||||||
|
"Window state for " + window.getUniqueIdentifier() + "\n" +
|
||||||
|
"-> Terminated: " + window.isTerminated() + "\n" +
|
||||||
|
"-> Name: " + window.getName() + "\n" +
|
||||||
|
"-> Title: " + window.getTitle() + "\n" +
|
||||||
|
"-> Size: " + window.getSize() + "\n" +
|
||||||
|
" -> Minimum: " + window.getMinimumSize() + "\n" +
|
||||||
|
" -> Maximum: " + window.getMaximumSize() + "\n" +
|
||||||
|
"-> Position: " + window.getPosition() + "\n" +
|
||||||
|
"-> Mode: " + window.getMode() + "\n" +
|
||||||
|
"-> Monitor: " + window.getMonitor() + "\n" +
|
||||||
|
"-> Resizable: " + window.isResizable() + "\n" +
|
||||||
|
"-> Borderless: " + window.isBorderless() + "\n" +
|
||||||
|
"-> Focusable: " + window.isFocusable() + "\n" +
|
||||||
|
"-> On top: " + window.isOnTop() + "\n" +
|
||||||
|
"-> Transparent: " + window.isTransparent() + "\n" +
|
||||||
|
"-> Rendering: " + window.isRendering()
|
||||||
|
);
|
||||||
|
|
||||||
reportDuration = System.currentTimeMillis() + 1000; // Update 'reportDuration'
|
reportDuration = System.currentTimeMillis() + 1000; // Update 'reportDuration'
|
||||||
splitDeltaTime.clear(); // Clear 'splitDeltaTime' list
|
splitDeltaTime.clear(); // Clear 'splitDeltaTime' list
|
||||||
}
|
}
|
||||||
|
@ -312,12 +349,21 @@ public final class RenderingSubsystem extends SubsystemClass {
|
||||||
* and if so, specifies it as the platform to use.
|
* and if so, specifies it as the platform to use.
|
||||||
*
|
*
|
||||||
* @param platform platform to try
|
* @param platform platform to try
|
||||||
|
* @param renderingPlatform {@link RenderingPlatform} used to log that the platform is unsupported (set to {@code null} to disable)
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
private void tryPlatform(int platform) {
|
private void tryPlatform(int platform, @Nullable RenderingPlatform renderingPlatform) {
|
||||||
if (glfwPlatformSupported(platform))
|
if (glfwPlatformSupported(platform))
|
||||||
glfwInitHint(GLFW_PLATFORM, platform);
|
if (platform != GLFW_PLATFORM_WAYLAND)
|
||||||
else
|
glfwInitHint(GLFW_PLATFORM, platform);
|
||||||
|
else {
|
||||||
|
Logger.warn("Wayland is not supported by the StarOpenSource Engine due to various issues with it, sorry.");
|
||||||
|
tryPlatform(GLFW_PLATFORM_X11, RenderingPlatform.X11);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (renderingPlatform != null)
|
||||||
|
Logger.warn("Platform RenderingPlatform." + renderingPlatform.name() + " is not supported GLFW. Using RenderingPlatform.ANY instead");
|
||||||
glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
|
glfwInitHint(GLFW_PLATFORM, GLFW_ANY_PLATFORM);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import de.staropensource.engine.base.implementable.Configuration;
|
||||||
import de.staropensource.engine.base.logging.Logger;
|
import de.staropensource.engine.base.logging.Logger;
|
||||||
import de.staropensource.engine.base.utility.PropertiesReader;
|
import de.staropensource.engine.base.utility.PropertiesReader;
|
||||||
import de.staropensource.engine.rendering.event.RenderingErrorEvent;
|
import de.staropensource.engine.rendering.event.RenderingErrorEvent;
|
||||||
|
import de.staropensource.engine.rendering.type.window.RenderingAdapter;
|
||||||
import de.staropensource.engine.rendering.type.window.RenderingPlatform;
|
import de.staropensource.engine.rendering.type.window.RenderingPlatform;
|
||||||
import de.staropensource.engine.rendering.type.window.VsyncMode;
|
import de.staropensource.engine.rendering.type.window.VsyncMode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
@ -97,24 +98,48 @@ public final class RenderingSubsystemConfiguration extends Configuration {
|
||||||
* Contains whether or not the delta time and
|
* Contains whether or not the delta time and
|
||||||
* FPS count should be logged to the console
|
* FPS count should be logged to the console
|
||||||
* every second.
|
* every second.
|
||||||
* <p>
|
|
||||||
* Changes will no longer be picked up as
|
|
||||||
* soon as the rendering loop is running.
|
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
* -- GETTER --
|
* -- GETTER --
|
||||||
* Returns whether or not the delta time and
|
* Returns whether or not the delta time and
|
||||||
* FPS count should be logged to the console
|
* FPS count should be logged to the console
|
||||||
* every second.
|
* every second.
|
||||||
* <p>
|
|
||||||
* Changes will no longer be picked up as
|
|
||||||
* soon as the rendering loop is running.
|
|
||||||
*
|
*
|
||||||
* @return print delta time and FPS count?
|
* @return print delta time and FPS count?
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
private boolean debugFrames;
|
private boolean debugFrames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains if to log the state of all
|
||||||
|
* windows every second.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns if to log the state of all
|
||||||
|
* windows every second.
|
||||||
|
*
|
||||||
|
* @return log states of all windows?
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
private boolean debugWindowStates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains if to allow updates to a window's
|
||||||
|
* position. May cause errors and crashes to
|
||||||
|
* appear, we do not know why.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns if to allow updates to a window's
|
||||||
|
* position. May cause errors and crashes to
|
||||||
|
* appear, we do not know why.
|
||||||
|
*
|
||||||
|
* @return allow window position updates?
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
private boolean debugAllowPositionUpdates;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the platform GLFW shall try initialising.
|
* Contains the platform GLFW shall try initialising.
|
||||||
|
@ -172,6 +197,18 @@ public final class RenderingSubsystemConfiguration extends Configuration {
|
||||||
private boolean errorRenderingFailures;
|
private boolean errorRenderingFailures;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the adapter bgfx shall use.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the adapter bgfx shall use.
|
||||||
|
*
|
||||||
|
* @return bgfx adapter
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
private RenderingAdapter renderingAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains which {@link VsyncMode} to use.
|
* Contains which {@link VsyncMode} to use.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -241,18 +278,27 @@ public final class RenderingSubsystemConfiguration extends Configuration {
|
||||||
case "debug" -> debug = parser.getBoolean(group + property);
|
case "debug" -> debug = parser.getBoolean(group + property);
|
||||||
case "debugInput" -> debugInput = parser.getBoolean(group + property);
|
case "debugInput" -> debugInput = parser.getBoolean(group + property);
|
||||||
case "debugFrames" -> debugFrames = parser.getBoolean(group + property);
|
case "debugFrames" -> debugFrames = parser.getBoolean(group + property);
|
||||||
|
case "debugWindowStates" -> debugWindowStates = parser.getBoolean(group + property);
|
||||||
|
case "debugAllowPositionUpdates" -> debugAllowPositionUpdates = parser.getBoolean(group + property);
|
||||||
|
|
||||||
case "initialPlatform" -> {
|
case "initialPlatform" -> {
|
||||||
try {
|
try {
|
||||||
initialPlatform = RenderingPlatform.valueOf(parser.getString(group + property).toUpperCase());
|
initialPlatform = RenderingPlatform.valueOf(parser.getString(group + property).toUpperCase());
|
||||||
} catch (IllegalArgumentException ignored) {
|
} catch (IllegalArgumentException ignored) {
|
||||||
Logger.error("Platform " + parser.getString(group + property) + " is not valid");
|
Logger.error("Rendering platform " + parser.getString(group + property) + " is not valid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "initialDisableLibdecor" -> initialDisableLibdecor = parser.getBoolean(group + property);
|
case "initialDisableLibdecor" -> initialDisableLibdecor = parser.getBoolean(group + property);
|
||||||
|
|
||||||
case "errorRenderingFailures" -> errorRenderingFailures = parser.getBoolean(group + property);
|
case "errorRenderingFailures" -> errorRenderingFailures = parser.getBoolean(group + property);
|
||||||
|
|
||||||
|
case "renderingAdapter" -> {
|
||||||
|
try {
|
||||||
|
renderingAdapter = RenderingAdapter.valueOf(parser.getString(group + property).toUpperCase());
|
||||||
|
} catch (IllegalArgumentException exception) {
|
||||||
|
Logger.error("Rendering adapter " + parser.getString(group + property) + " is not valid");
|
||||||
|
}
|
||||||
|
}
|
||||||
case "vsyncMode" -> {
|
case "vsyncMode" -> {
|
||||||
try {
|
try {
|
||||||
vsyncMode = VsyncMode.valueOf(parser.getString(group + property).toUpperCase());
|
vsyncMode = VsyncMode.valueOf(parser.getString(group + property).toUpperCase());
|
||||||
|
@ -271,21 +317,26 @@ public final class RenderingSubsystemConfiguration extends Configuration {
|
||||||
if (!debug) {
|
if (!debug) {
|
||||||
debugInput = false;
|
debugInput = false;
|
||||||
debugFrames = false;
|
debugFrames = false;
|
||||||
|
debugWindowStates = false;
|
||||||
|
debugAllowPositionUpdates = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public void loadDefaultConfiguration() {
|
public void loadDefaultConfiguration() {
|
||||||
debug = false;
|
debug = true;
|
||||||
debugInput = false;
|
debugInput = false;
|
||||||
debugFrames = false;
|
debugFrames = true;
|
||||||
|
debugWindowStates = true;
|
||||||
|
debugAllowPositionUpdates = true;
|
||||||
|
|
||||||
initialPlatform = RenderingPlatform.ANY;
|
initialPlatform = RenderingPlatform.ANY;
|
||||||
initialDisableLibdecor = false;
|
initialDisableLibdecor = false;
|
||||||
|
|
||||||
errorRenderingFailures = true;
|
errorRenderingFailures = true;
|
||||||
|
|
||||||
|
renderingAdapter = RenderingAdapter.ANY;
|
||||||
vsyncMode = VsyncMode.ON;
|
vsyncMode = VsyncMode.ON;
|
||||||
maximumFramesPerSecond = 60;
|
maximumFramesPerSecond = 60;
|
||||||
}
|
}
|
||||||
|
@ -297,12 +348,15 @@ public final class RenderingSubsystemConfiguration extends Configuration {
|
||||||
case "debug" -> { return debug; }
|
case "debug" -> { return debug; }
|
||||||
case "debugInput" -> { return debugInput; }
|
case "debugInput" -> { return debugInput; }
|
||||||
case "debugFrames" -> { return debugFrames; }
|
case "debugFrames" -> { return debugFrames; }
|
||||||
|
case "debugWindowStates" -> { return debugWindowStates; }
|
||||||
|
case "debugAllowPositionUpdates" -> { return debugAllowPositionUpdates; }
|
||||||
|
|
||||||
case "initialPlatform" -> { return initialPlatform; }
|
case "initialPlatform" -> { return initialPlatform; }
|
||||||
case "disableLibdecor" -> { return initialDisableLibdecor; }
|
case "disableLibdecor" -> { return initialDisableLibdecor; }
|
||||||
|
|
||||||
case "errorRenderingFailures" -> { return errorRenderingFailures; }
|
case "errorRenderingFailures" -> { return errorRenderingFailures; }
|
||||||
|
|
||||||
|
case "renderingAdapter" -> { return renderingAdapter; }
|
||||||
case "vsyncMode" -> { return vsyncMode; }
|
case "vsyncMode" -> { return vsyncMode; }
|
||||||
case "maximumFramesPerSecond" -> { return maximumFramesPerSecond; }
|
case "maximumFramesPerSecond" -> { return maximumFramesPerSecond; }
|
||||||
default -> { return null; }
|
default -> { return null; }
|
||||||
|
|
|
@ -21,7 +21,6 @@ package de.staropensource.engine.rendering.callback;
|
||||||
|
|
||||||
import de.staropensource.engine.rendering.type.Window;
|
import de.staropensource.engine.rendering.type.Window;
|
||||||
import de.staropensource.engine.rendering.event.InputEvent;
|
import de.staropensource.engine.rendering.event.InputEvent;
|
||||||
import de.staropensource.engine.rendering.callback.WindowCallback;
|
|
||||||
import de.staropensource.engine.rendering.type.input.Key;
|
import de.staropensource.engine.rendering.type.input.Key;
|
||||||
import de.staropensource.engine.rendering.type.input.KeyState;
|
import de.staropensource.engine.rendering.type.input.KeyState;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||||
|
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||||
|
* Licensed under the GNU Affero General Public License v3
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.staropensource.engine.rendering.event;
|
||||||
|
|
||||||
|
import de.staropensource.engine.base.implementable.Event;
|
||||||
|
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the rendering thread exits due to an unhandled exception.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public final class RenderingThreadThrowableEvent implements Event {
|
||||||
|
/**
|
||||||
|
* Creates and initializes an instance of this event.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public RenderingThreadThrowableEvent() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @deprecated use the {@code callEvent} method with arguments
|
||||||
|
* @see #callEvent(Throwable)
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@Override
|
||||||
|
public void callEvent() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits the event and calls all event listeners.
|
||||||
|
*
|
||||||
|
* @param throwable thrown {@link Throwable}
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public void callEvent(@NotNull Throwable throwable) {
|
||||||
|
EventHelper.invokeAnnotatedMethods(getClass(), throwable);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,379 @@
|
||||||
|
/*
|
||||||
|
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||||
|
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||||
|
* Licensed under the GNU Affero General Public License v3
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.staropensource.engine.rendering.renderer;
|
||||||
|
|
||||||
|
import de.staropensource.engine.base.logging.Logger;
|
||||||
|
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
||||||
|
import de.staropensource.engine.base.utility.misc.NumberUtil;
|
||||||
|
import de.staropensource.engine.rendering.RenderingSubsystemConfiguration;
|
||||||
|
import de.staropensource.engine.rendering.exception.NotOnMainThreadException;
|
||||||
|
import de.staropensource.engine.rendering.type.FrameHandler;
|
||||||
|
import de.staropensource.engine.rendering.type.Monitor;
|
||||||
|
import de.staropensource.engine.rendering.type.Window;
|
||||||
|
import de.staropensource.engine.rendering.type.window.VsyncMode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.lwjgl.bgfx.BGFX.*;
|
||||||
|
import static org.lwjgl.glfw.GLFW.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders all windows out.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "JavadocDeclaration" })
|
||||||
|
public final class Renderer {
|
||||||
|
/**
|
||||||
|
* Contains all frame handlers.
|
||||||
|
* <p>
|
||||||
|
* Frame handlers are invoked before
|
||||||
|
* all windows are rendered, allowing
|
||||||
|
* the application or game to respond
|
||||||
|
* to frame renders.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
private static final @NotNull List<@NotNull FrameHandler> frameHandlers = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains if the renderer has been initialized.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns if the renderer has been initialized.
|
||||||
|
*
|
||||||
|
* @return renderer initialized?
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static boolean initialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains if the renderer is running.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns if the renderer is running.
|
||||||
|
*
|
||||||
|
* @return renderer running?
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static boolean running = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the frame count aka.
|
||||||
|
* the amount of frames rendered.
|
||||||
|
* <p>
|
||||||
|
* Updated every frame.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the frame count aka.
|
||||||
|
* the amount of frames rendered.
|
||||||
|
* <p>
|
||||||
|
* Updated every frame.
|
||||||
|
*
|
||||||
|
* @return amount of frames rendered
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static long frameCount = 0L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the delta time, also
|
||||||
|
* known as the render time.
|
||||||
|
* <p>
|
||||||
|
* Updated every second.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the delta time, also
|
||||||
|
* known as the render time.
|
||||||
|
* <p>
|
||||||
|
* Updated every second.
|
||||||
|
*
|
||||||
|
* @return delta time
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static double deltaTime = 0d;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the frames per second (FPS) count.
|
||||||
|
* <p>
|
||||||
|
* Updated every second.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the frames per second (FPS) count.
|
||||||
|
* <p>
|
||||||
|
* Updated every second.
|
||||||
|
*
|
||||||
|
* @return frames per second
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static double framesPerSecond = 0d;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the time it took
|
||||||
|
* to calculate the last frame.
|
||||||
|
* <p>
|
||||||
|
* Updated every frame.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Contains the time it took
|
||||||
|
* to calculate the last frame.
|
||||||
|
* <p>
|
||||||
|
* Updated every frame.
|
||||||
|
*
|
||||||
|
* @return last frame time
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private static Map<@NotNull String, @NotNull Long> lastFrameTime = Collections.unmodifiableMap(new HashMap<>());
|
||||||
|
|
||||||
|
|
||||||
|
// ----> Initialization
|
||||||
|
/**
|
||||||
|
* Initializes the renderer.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public static void initialize() {
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
addFrameHandler(new FrameHandler() {
|
||||||
|
@Override
|
||||||
|
public @NotNull FrameHandler.Priority getPriority() {
|
||||||
|
return Priority.VERY_IMPORTANT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
bgfx_set_view_clear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x000000, 1.0f, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
addFrameHandler(new FrameHandler() {
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public @NotNull FrameHandler.Priority getPriority() {
|
||||||
|
return Priority.VERY_UNIMPORTANT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int offset = 2;
|
||||||
|
|
||||||
|
bgfx_dbg_text_clear(0, false);
|
||||||
|
bgfx_dbg_text_printf(0, 0, 0x0f, "It's " + NumberUtil.padNumbers(LocalTime.now().getHour(), 2) + ":" + NumberUtil.padNumbers(LocalTime.now().getMinute(), 2) + ":" + NumberUtil.padNumbers(LocalTime.now().getSecond(), 2));
|
||||||
|
bgfx_dbg_text_printf(0, 1, 0x0f, "LFT.size(): " + lastFrameTime.size());
|
||||||
|
for (String item : lastFrameTime.keySet()) {
|
||||||
|
bgfx_dbg_text_printf(0, offset, 0x0f, item + ": " + lastFrameTime.get(item) + "ms");
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----> Frame handler management
|
||||||
|
/**
|
||||||
|
* Adds the specified frame handler.
|
||||||
|
*
|
||||||
|
* @param frameHandler {@link FrameHandler} to add
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public static void addFrameHandler(@NotNull FrameHandler frameHandler) {
|
||||||
|
frameHandlers.add(frameHandler);
|
||||||
|
frameHandlers.sort(Comparator.comparing(FrameHandler::getPriority));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified frame handler.
|
||||||
|
*
|
||||||
|
* @param frameHandler {@link FrameHandler} to remove
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public static void removeFrameHandler(@NotNull FrameHandler frameHandler) {
|
||||||
|
frameHandlers.remove(frameHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----> Rendering logic
|
||||||
|
/**
|
||||||
|
* Starts the renderer.
|
||||||
|
*
|
||||||
|
* @throws NotOnMainThreadException if not running on the main thread
|
||||||
|
* @throws RuntimeException on major rendering error
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public static void start() throws RuntimeException {
|
||||||
|
// Check if running on main thread
|
||||||
|
if (!Miscellaneous.onMainThread())
|
||||||
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
|
String threadName = Thread.currentThread().getName();
|
||||||
|
int threadPriority = Thread.currentThread().getPriority();
|
||||||
|
RuntimeException exception = null;
|
||||||
|
|
||||||
|
// Update thread
|
||||||
|
Thread.currentThread().setName("Rendering thread");
|
||||||
|
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
|
||||||
|
|
||||||
|
// Start renderer
|
||||||
|
running = true;
|
||||||
|
try {
|
||||||
|
render();
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
exception = new RuntimeException("Renderer failed", throwable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert thread changes
|
||||||
|
Thread.currentThread().setName(threadName);
|
||||||
|
Thread.currentThread().setPriority(threadPriority);
|
||||||
|
|
||||||
|
// Throw if necessary
|
||||||
|
if (exception != null)
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders all windows.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({ "InfiniteLoopStatement" })
|
||||||
|
private static void render() throws Throwable {
|
||||||
|
long previousFrameCount = 0L; // Frame count one second ago
|
||||||
|
LinkedList<Long> deltaTimeFractions = new LinkedList<>(); // Contains all delta time fractions
|
||||||
|
Map<String, Long> execTimes = new LinkedHashMap<>(); // Contains the amount of time of all rendering operations
|
||||||
|
long timesWait; // Time to wait until the next frame
|
||||||
|
long timesPSO = System.currentTimeMillis() + 1000; // Time to wait until invoking per-second operations
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// Invoke frame handlers
|
||||||
|
for (FrameHandler frameHandler : frameHandlers)
|
||||||
|
execTimes.put("Frame handler '" + frameHandler.getClass().getName() + "'", Miscellaneous.measureExecutionTime(frameHandler::run));
|
||||||
|
|
||||||
|
|
||||||
|
// Perform rendering
|
||||||
|
execTimes.put("Rendering", Miscellaneous.measureExecutionTime(() -> {
|
||||||
|
// Poll for events
|
||||||
|
glfwPollEvents();
|
||||||
|
|
||||||
|
// Reset backbuffer
|
||||||
|
bgfx_reset(Window.getWindows().getFirst().getSize().getX(), Window.getWindows().getFirst().getSize().getY(), RenderingSubsystemConfiguration.getInstance().getVsyncMode() == VsyncMode.ON ? BGFX_RESET_VSYNC : BGFX_RESET_NONE, BGFX_TEXTURE_FORMAT_RGBA4);
|
||||||
|
|
||||||
|
// Render all windows
|
||||||
|
for (Window window : Window.getWindows())
|
||||||
|
if (window.isRendering()) {
|
||||||
|
window.updateState();
|
||||||
|
window.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance to next frame
|
||||||
|
bgfx_frame(false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
// Determine time to wait for the next frame
|
||||||
|
execTimes.put("Waiting", 0L);
|
||||||
|
switch (RenderingSubsystemConfiguration.getInstance().getVsyncMode()) {
|
||||||
|
case OFF -> execTimes.replace("Waiting", (long) (1d / RenderingSubsystemConfiguration.getInstance().getMaximumFramesPerSecond() * 1000d));
|
||||||
|
case ON -> {
|
||||||
|
for (Monitor monitor : Monitor.getMonitors())
|
||||||
|
if (monitor.getRefreshRate() > execTimes.get("Waiting"))
|
||||||
|
execTimes.replace("Waiting", (long) monitor.getRefreshRate());
|
||||||
|
}
|
||||||
|
default -> {}
|
||||||
|
}
|
||||||
|
for (String time : execTimes.keySet())
|
||||||
|
if (!time.equals("Waiting"))
|
||||||
|
execTimes.replace("Waiting", execTimes.get("Waiting") - execTimes.get(time));
|
||||||
|
|
||||||
|
// Wait until next frame
|
||||||
|
if (execTimes.get("Waiting") > 0) {
|
||||||
|
timesWait = execTimes.get("Waiting") + System.currentTimeMillis();
|
||||||
|
|
||||||
|
while (System.currentTimeMillis() < timesWait)
|
||||||
|
Thread.onSpinWait();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Perform per-frame operations
|
||||||
|
frameCount += 1;
|
||||||
|
lastFrameTime = new HashMap<>(execTimes);
|
||||||
|
deltaTimeFractions.add(execTimes.get("Rendering") + execTimes.get("Waiting"));
|
||||||
|
execTimes.clear();
|
||||||
|
|
||||||
|
|
||||||
|
// Perform per-second operations
|
||||||
|
if (System.currentTimeMillis() >= timesPSO) {
|
||||||
|
// Calculate delta time and FPS count
|
||||||
|
deltaTime = NumberUtil.calculateMeanLong(deltaTimeFractions);
|
||||||
|
framesPerSecond = 1000 / deltaTime;
|
||||||
|
|
||||||
|
// Log frame count
|
||||||
|
if (RenderingSubsystemConfiguration.getInstance().isDebugFrames())
|
||||||
|
Logger.diag("Frames " + previousFrameCount + "-" + frameCount + "\n-> Frames/s: " + framesPerSecond + "\n-> Delta time: " + deltaTime);
|
||||||
|
|
||||||
|
// Log window states
|
||||||
|
if (RenderingSubsystemConfiguration.getInstance().isDebugWindowStates())
|
||||||
|
for (Window window : Window.getWindows())
|
||||||
|
Logger.diag(
|
||||||
|
"Window state for " + window.getUniqueIdentifier() + "\n" +
|
||||||
|
"-> Terminated: " + window.isTerminated() + "\n" +
|
||||||
|
"-> Name: " + window.getName() + "\n" +
|
||||||
|
"-> Title: " + window.getTitle() + "\n" +
|
||||||
|
"-> Size: " + window.getSize() + "\n" +
|
||||||
|
" -> Minimum: " + window.getMinimumSize() + "\n" +
|
||||||
|
" -> Maximum: " + window.getMaximumSize() + "\n" +
|
||||||
|
"-> Position: " + window.getPosition() + "\n" +
|
||||||
|
"-> Mode: " + window.getMode() + "\n" +
|
||||||
|
"-> Monitor: " + window.getMonitor() + "\n" +
|
||||||
|
"-> Resizable: " + window.isResizable() + "\n" +
|
||||||
|
"-> Borderless: " + window.isBorderless() + "\n" +
|
||||||
|
"-> Focusable: " + window.isFocusable() + "\n" +
|
||||||
|
"-> On top: " + window.isOnTop() + "\n" +
|
||||||
|
"-> Transparent: " + window.isTransparent() + "\n" +
|
||||||
|
"-> Rendering: " + window.isRendering()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Reset per-second variables
|
||||||
|
previousFrameCount = frameCount;
|
||||||
|
deltaTimeFractions.clear();
|
||||||
|
timesPSO = System.currentTimeMillis() + 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* STAROPENSOURCE ENGINE SOURCE FILE
|
||||||
|
* Copyright (c) 2024 The StarOpenSource Engine Authors
|
||||||
|
* Licensed under the GNU Affero General Public License v3
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.staropensource.engine.rendering.type;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for performing actions
|
||||||
|
* before a frame is rendered.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public interface FrameHandler {
|
||||||
|
/**
|
||||||
|
* Returns the priority this frame handler has.
|
||||||
|
*
|
||||||
|
* @return priority
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@NotNull FrameHandler.Priority getPriority();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes this frame handler.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
void run();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains all priority levels
|
||||||
|
* a {@link FrameHandler} can have.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
enum Priority {
|
||||||
|
/**
|
||||||
|
* {@link FrameHandler}s with
|
||||||
|
* this priority are called first.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
VERY_IMPORTANT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link FrameHandler}s with
|
||||||
|
* this priority are called 2nd.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
IMPORTANT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link FrameHandler}s with
|
||||||
|
* this priority are called 3rd.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
DEFAULT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link FrameHandler}s with
|
||||||
|
* this priority are called 4th.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
UNIMPORTANT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link FrameHandler}s with
|
||||||
|
* this priority are called last.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
VERY_UNIMPORTANT,
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,19 +22,21 @@ package de.staropensource.engine.rendering.type;
|
||||||
import de.staropensource.engine.base.logging.Logger;
|
import de.staropensource.engine.base.logging.Logger;
|
||||||
import de.staropensource.engine.base.type.Tristate;
|
import de.staropensource.engine.base.type.Tristate;
|
||||||
import de.staropensource.engine.base.type.vector.Vec2i;
|
import de.staropensource.engine.base.type.vector.Vec2i;
|
||||||
import de.staropensource.engine.base.utility.Miscellaneous;
|
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
||||||
|
import de.staropensource.engine.base.utility.misc.TypeConversion;
|
||||||
|
import de.staropensource.engine.rendering.RenderingSubsystemConfiguration;
|
||||||
import de.staropensource.engine.rendering.callback.KeyCallback;
|
import de.staropensource.engine.rendering.callback.KeyCallback;
|
||||||
import de.staropensource.engine.rendering.callback.MouseButtonCallback;
|
import de.staropensource.engine.rendering.callback.MouseButtonCallback;
|
||||||
import de.staropensource.engine.rendering.event.InputEvent;
|
import de.staropensource.engine.rendering.event.InputEvent;
|
||||||
import de.staropensource.engine.rendering.exception.NotOnMainThreadException;
|
import de.staropensource.engine.rendering.exception.NotOnMainThreadException;
|
||||||
import de.staropensource.engine.rendering.exception.WindowCreationFailureException;
|
import de.staropensource.engine.rendering.exception.WindowCreationFailureException;
|
||||||
import de.staropensource.engine.rendering.type.window.WindowMode;
|
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.bgfx.BGFX;
|
||||||
import org.lwjgl.bgfx.BGFXInit;
|
import org.lwjgl.bgfx.BGFXInit;
|
||||||
import org.lwjgl.glfw.*;
|
import org.lwjgl.glfw.*;
|
||||||
import org.lwjgl.stb.STBImage;
|
import org.lwjgl.stb.STBImage;
|
||||||
|
@ -60,7 +62,7 @@ import static org.lwjgl.system.MemoryUtil.*;
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@SuppressWarnings({ "JavadocDeclaration" })
|
@SuppressWarnings({ "unused", "JavadocDeclaration" })
|
||||||
public final class Window implements AutoCloseable {
|
public final class Window implements AutoCloseable {
|
||||||
/**
|
/**
|
||||||
* A set of all active windows.
|
* A set of all active windows.
|
||||||
|
@ -69,18 +71,7 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
private static final @NotNull List<@NotNull Window> windows = new ArrayList<>();
|
private static final @NotNull List<@NotNull Window> windows = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
// -----> Internal fields
|
||||||
* Contains the internal window identifier.
|
|
||||||
*
|
|
||||||
* @since v1-alpha9
|
|
||||||
* -- GETTER --
|
|
||||||
* Returns the internal window identifier.
|
|
||||||
*
|
|
||||||
* @return window identifier
|
|
||||||
* @since v1-alpha9
|
|
||||||
*/
|
|
||||||
private long identifier;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains if this window is fresh.
|
* Contains if this window is fresh.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -99,8 +90,39 @@ public final class Window implements AutoCloseable {
|
||||||
* @return fresh flag state
|
* @return fresh flag state
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
private boolean fresh = true;
|
@Getter(value = AccessLevel.NONE)
|
||||||
|
@Setter(value = AccessLevel.NONE)
|
||||||
|
private boolean fresh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the internal GLFW window identifier.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the internal GLFW window identifier.
|
||||||
|
*
|
||||||
|
* @return GLFW window identifier
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter(value = AccessLevel.NONE)
|
||||||
|
@Setter(value = AccessLevel.NONE)
|
||||||
|
private long internalWindowIdentifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the internal bgfx view identifier.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
* -- GETTER --
|
||||||
|
* Returns the internal bgfx view identifier.
|
||||||
|
*
|
||||||
|
* @return bgfx view identifier
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
@Getter(value = AccessLevel.NONE)
|
||||||
|
@Setter(value = AccessLevel.NONE)
|
||||||
|
private int internalViewIdentifier;
|
||||||
|
|
||||||
|
// -----> Window properties
|
||||||
/**
|
/**
|
||||||
* Contains if this window can be interacted with or not.
|
* Contains if this window can be interacted with or not.
|
||||||
*
|
*
|
||||||
|
@ -258,7 +280,7 @@ public final class Window implements AutoCloseable {
|
||||||
private @NotNull Vec2i position;
|
private @NotNull Vec2i position;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains in which {@link WindowMode} this window is in.
|
* Contains in which {@link Mode} this window is in.
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
* -- GETTER --
|
* -- GETTER --
|
||||||
|
@ -267,7 +289,7 @@ public final class Window implements AutoCloseable {
|
||||||
* @return window mode
|
* @return window mode
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
private @NotNull WindowMode windowMode;
|
private @NotNull Window.Mode mode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains on which {@link Monitor} the window is displayed on.
|
* Contains on which {@link Monitor} the window is displayed on.
|
||||||
|
@ -287,24 +309,6 @@ public final class Window implements AutoCloseable {
|
||||||
@Setter
|
@Setter
|
||||||
private @NotNull Monitor monitor;
|
private @NotNull Monitor monitor;
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains how fast the window may update it's contents.
|
|
||||||
*
|
|
||||||
* @since v1-alpha9
|
|
||||||
* -- GETTER --
|
|
||||||
* Returns how fast the window may update it's contents.
|
|
||||||
*
|
|
||||||
* @return new window frame limit
|
|
||||||
* @since v1-alpha9
|
|
||||||
* -- SETTER --
|
|
||||||
* Sets how fast the window may update it's contents.
|
|
||||||
*
|
|
||||||
* @param framerate new frame limit
|
|
||||||
* @since v1-alpha9
|
|
||||||
*/
|
|
||||||
@Setter
|
|
||||||
private int framerate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains if this window can be resized by the user.
|
* Contains if this window can be resized by the user.
|
||||||
*
|
*
|
||||||
|
@ -403,16 +407,20 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
private GLFWMouseButtonCallback mouseButtonCallback;
|
private GLFWMouseButtonCallback mouseButtonCallback;
|
||||||
|
|
||||||
|
|
||||||
|
// -----> Static methods
|
||||||
/**
|
/**
|
||||||
* Returns a set of active windows.
|
* Returns a set of active windows.
|
||||||
*
|
*
|
||||||
* @return active windows
|
* @return active windows
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public static @NotNull HashSet<@NotNull Window> getWindows() {
|
public static @NotNull List<@NotNull Window> getWindows() {
|
||||||
return new HashSet<>(windows);
|
return Collections.unmodifiableList(windows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -----> Initialization
|
||||||
/**
|
/**
|
||||||
* Creates and initializes an instance of this abstract class.
|
* Creates and initializes an instance of this abstract class.
|
||||||
*
|
*
|
||||||
|
@ -423,7 +431,7 @@ public final class Window implements AutoCloseable {
|
||||||
* @param minimumSize minimum size
|
* @param minimumSize minimum size
|
||||||
* @param maximumSize maximum size
|
* @param maximumSize maximum size
|
||||||
* @param position position
|
* @param position position
|
||||||
* @param windowMode window mode
|
* @param mode window mode
|
||||||
* @param monitor monitor
|
* @param monitor monitor
|
||||||
* @param resizable resizable flag
|
* @param resizable resizable flag
|
||||||
* @param borderless borderless flag
|
* @param borderless borderless flag
|
||||||
|
@ -441,7 +449,7 @@ public final class Window implements AutoCloseable {
|
||||||
@NotNull Vec2i minimumSize,
|
@NotNull Vec2i minimumSize,
|
||||||
@NotNull Vec2i maximumSize,
|
@NotNull Vec2i maximumSize,
|
||||||
@NotNull Vec2i position,
|
@NotNull Vec2i position,
|
||||||
@NotNull WindowMode windowMode,
|
@NotNull Window.Mode mode,
|
||||||
@NotNull Monitor monitor,
|
@NotNull Monitor monitor,
|
||||||
boolean resizable,
|
boolean resizable,
|
||||||
boolean borderless,
|
boolean borderless,
|
||||||
|
@ -450,7 +458,11 @@ public final class Window implements AutoCloseable {
|
||||||
boolean transparent,
|
boolean transparent,
|
||||||
boolean rendering) throws NotOnMainThreadException {
|
boolean rendering) throws NotOnMainThreadException {
|
||||||
// Initialize variables
|
// Initialize variables
|
||||||
|
this.fresh = true;
|
||||||
|
this.internalWindowIdentifier = 0L;
|
||||||
|
this.internalViewIdentifier = 0;
|
||||||
this.uniqueIdentifier = UUID.randomUUID();
|
this.uniqueIdentifier = UUID.randomUUID();
|
||||||
|
this.terminated = false;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.icons = icons;
|
this.icons = icons;
|
||||||
|
@ -458,7 +470,7 @@ public final class Window implements AutoCloseable {
|
||||||
this.minimumSize = minimumSize;
|
this.minimumSize = minimumSize;
|
||||||
this.maximumSize = maximumSize;
|
this.maximumSize = maximumSize;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.windowMode = windowMode;
|
this.mode = mode;
|
||||||
this.monitor = monitor;
|
this.monitor = monitor;
|
||||||
this.resizable = resizable;
|
this.resizable = resizable;
|
||||||
this.borderless = borderless;
|
this.borderless = borderless;
|
||||||
|
@ -468,25 +480,45 @@ public final class Window implements AutoCloseable {
|
||||||
this.rendering = rendering;
|
this.rendering = rendering;
|
||||||
|
|
||||||
// Log about window creation
|
// Log about window creation
|
||||||
Logger.diag("Creating new window with properties: uniqueIdentifier=" + uniqueIdentifier + " name=\"" + name + "\" title=\"" + title + "\" icons=" + Arrays.toString(icons) + " size=" + size + " minimumSize=" + minimumSize + " maximumSize=" + maximumSize + " position=" + position + " windowMode=" + windowMode + " monitor=" + monitor.getUniqueIdentifier() + " (" + monitor.getName() + ") resizable=" + resizable + " borderless=" + borderless + " focusable=" + focusable + " onTop=" + onTop + " transparent=" + transparent + " rendering=" + rendering);
|
Logger.verb("Creating new window " + this.uniqueIdentifier + "\n" +
|
||||||
|
"-> Name: " + this.name + "\n" +
|
||||||
|
"-> Title: " + this.title + "\n" +
|
||||||
|
"-> Size: " + this.size + "\n" +
|
||||||
|
" -> Minimum: " + this.minimumSize + "\n" +
|
||||||
|
" -> Maximum: " + this.maximumSize + "\n" +
|
||||||
|
"-> Position: " + this.position + "\n" +
|
||||||
|
"-> Mode: " + this.mode + "\n" +
|
||||||
|
"-> Monitor: " + this.monitor + "\n" +
|
||||||
|
"-> Resizable: " + this.resizable + "\n" +
|
||||||
|
"-> Borderless: " + this.borderless + "\n" +
|
||||||
|
"-> Focusable: " + this.focusable + "\n" +
|
||||||
|
"-> On top: " + this.onTop + "\n" +
|
||||||
|
"-> Transparent: " + this.transparent + "\n" +
|
||||||
|
"-> Rendering: " + this.rendering
|
||||||
|
);
|
||||||
|
|
||||||
// Allow windowing API to initialize window
|
// Check if another window already exists
|
||||||
|
if (!Window.getWindows().isEmpty())
|
||||||
|
Logger.crash("Window already present\nThe StarOpenSource Engine is unable to initialize more than one window at the moment, sorry.");
|
||||||
|
|
||||||
|
// Initialize window
|
||||||
initializeWindow();
|
initializeWindow();
|
||||||
|
|
||||||
// Update state
|
// Update state
|
||||||
updateState();
|
updateState();
|
||||||
|
|
||||||
|
// Initialize bgfx
|
||||||
|
if (glfwGetPlatform() != GLFW_PLATFORM_NULL)
|
||||||
|
initBgfx();
|
||||||
|
|
||||||
// Add to window set
|
// Add to window set
|
||||||
windows.add(this);
|
windows.add(this);
|
||||||
fresh = false;
|
fresh = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows the windowing API to initialize the window.
|
* Initializes this window.
|
||||||
* <p>
|
|
||||||
* NEVER place any code in the constructor. Instead, write
|
|
||||||
* API-specific window initialization code in here
|
|
||||||
* or stuff may break unexpectedly.
|
|
||||||
*
|
*
|
||||||
* @throws NotOnMainThreadException if not running on the main thread
|
* @throws NotOnMainThreadException if not running on the main thread
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
|
@ -504,12 +536,13 @@ public final class Window implements AutoCloseable {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set window hints
|
// Set window hints
|
||||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // The window's visibility is later changed in setWindowState, this is just for setting up the window
|
if (RenderingSubsystemConfiguration.getInstance().isDebugAllowPositionUpdates()) {
|
||||||
glfwWindowHint(GLFW_POSITION_X, getPosition().getX());
|
glfwWindowHint(GLFW_POSITION_X, getPosition().getX());
|
||||||
glfwWindowHint(GLFW_POSITION_Y, getPosition().getY());
|
glfwWindowHint(GLFW_POSITION_Y, getPosition().getY());
|
||||||
|
}
|
||||||
glfwWindowHint(GLFW_CENTER_CURSOR, 0);
|
glfwWindowHint(GLFW_CENTER_CURSOR, 0);
|
||||||
glfwWindowHint(GLFW_FOCUSED, Miscellaneous.getIntegerizedBoolean(focused));
|
glfwWindowHint(GLFW_FOCUSED, TypeConversion.booleanToInteger(focused));
|
||||||
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, Miscellaneous.getIntegerizedBoolean(isTransparent()));
|
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, TypeConversion.booleanToInteger(transparent));
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
|
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_FALSE);
|
||||||
glfwWindowHintString(GLFW_WAYLAND_APP_ID, getName());
|
glfwWindowHintString(GLFW_WAYLAND_APP_ID, getName());
|
||||||
|
@ -517,8 +550,8 @@ public final class Window implements AutoCloseable {
|
||||||
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, getName());
|
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, getName());
|
||||||
|
|
||||||
// Create window
|
// Create window
|
||||||
identifier = glfwCreateWindow(getSize().getX(), getSize().getY(), getTitle(), NULL, NULL);
|
internalWindowIdentifier = glfwCreateWindow(getSize().getX(), getSize().getY(), getTitle(), NULL, NULL);
|
||||||
if (identifier == NULL)
|
if (internalWindowIdentifier == NULL)
|
||||||
throw new WindowCreationFailureException();
|
throw new WindowCreationFailureException();
|
||||||
|
|
||||||
// Own context
|
// Own context
|
||||||
|
@ -532,18 +565,15 @@ public final class Window implements AutoCloseable {
|
||||||
mouseButtonCallback = GLFWMouseButtonCallback.create(new MouseButtonCallback(this));
|
mouseButtonCallback = GLFWMouseButtonCallback.create(new MouseButtonCallback(this));
|
||||||
|
|
||||||
// Set callback
|
// Set callback
|
||||||
glfwSetKeyCallback(identifier, keyCallback);
|
glfwSetKeyCallback(internalWindowIdentifier, keyCallback);
|
||||||
glfwSetMouseButtonCallback(identifier, mouseButtonCallback);
|
glfwSetMouseButtonCallback(internalWindowIdentifier, mouseButtonCallback);
|
||||||
|
|
||||||
// Update the window state
|
// Update the window state
|
||||||
setIcons(getIcons());
|
setIcons(getIcons());
|
||||||
setSize(getSize());
|
setSize(getSize());
|
||||||
setMinimumSize(getMinimumSize());
|
setMinimumSize(getMinimumSize());
|
||||||
setMaximumSize(getMaximumSize());
|
setMaximumSize(getMaximumSize());
|
||||||
setWindowMode(getWindowMode());
|
setMode(getMode());
|
||||||
|
|
||||||
// Initialize bgfx
|
|
||||||
initBgfx();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -552,6 +582,10 @@ public final class Window implements AutoCloseable {
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
private void initBgfx() {
|
private void initBgfx() {
|
||||||
|
// Ensure the window is not terminated
|
||||||
|
if (terminated)
|
||||||
|
return;
|
||||||
|
|
||||||
try (MemoryStack stack = stackPush()) {
|
try (MemoryStack stack = stackPush()) {
|
||||||
Logger.verb("Initializing bgfx");
|
Logger.verb("Initializing bgfx");
|
||||||
|
|
||||||
|
@ -560,13 +594,29 @@ public final class Window implements AutoCloseable {
|
||||||
BGFXInit init = BGFXInit.calloc(stack);
|
BGFXInit init = BGFXInit.calloc(stack);
|
||||||
bgfx_init_ctor(init);
|
bgfx_init_ctor(init);
|
||||||
|
|
||||||
|
// Set adapter
|
||||||
|
Logger.diag("Setting adapter");
|
||||||
|
init.vendorId(switch (RenderingSubsystemConfiguration.getInstance().getRenderingAdapter()) {
|
||||||
|
case ANY -> BGFX_PCI_ID_NONE;
|
||||||
|
case SOFTWARE -> BGFX_PCI_ID_SOFTWARE_RASTERIZER;
|
||||||
|
case AMD -> BGFX_PCI_ID_AMD;
|
||||||
|
case APPLE -> BGFX_PCI_ID_APPLE;
|
||||||
|
case INTEL -> BGFX_PCI_ID_INTEL;
|
||||||
|
case NVIDIA -> BGFX_PCI_ID_NVIDIA;
|
||||||
|
case MICROSOFT -> BGFX_PCI_ID_MICROSOFT;
|
||||||
|
});
|
||||||
|
|
||||||
// Set initial resolution
|
// Set initial resolution
|
||||||
Logger.diag("Setting initial resolution");
|
Logger.diag("Setting initial resolution");
|
||||||
init
|
init
|
||||||
.resolution(it -> it
|
.resolution(
|
||||||
.width(size.getX())
|
it -> it
|
||||||
.height(size.getY())
|
.width(size.getX())
|
||||||
.reset(BGFX_RESET_VSYNC));
|
.height(size.getY())
|
||||||
|
.reset(
|
||||||
|
BGFX_RESET_VSYNC
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// Determine platform to render for
|
// Determine platform to render for
|
||||||
Logger.diag("Setting platform");
|
Logger.diag("Setting platform");
|
||||||
|
@ -574,18 +624,17 @@ public final class Window implements AutoCloseable {
|
||||||
case GLFW_PLATFORM_X11 -> init
|
case GLFW_PLATFORM_X11 -> init
|
||||||
.platformData()
|
.platformData()
|
||||||
.ndt(GLFWNativeX11.glfwGetX11Display())
|
.ndt(GLFWNativeX11.glfwGetX11Display())
|
||||||
.nwh(GLFWNativeX11.glfwGetX11Window(identifier));
|
.nwh(GLFWNativeX11.glfwGetX11Window(internalWindowIdentifier));
|
||||||
case GLFW_PLATFORM_WAYLAND -> init
|
case GLFW_PLATFORM_WAYLAND -> init
|
||||||
.platformData()
|
.platformData()
|
||||||
.ndt(GLFWNativeWayland.glfwGetWaylandDisplay())
|
.ndt(GLFWNativeWayland.glfwGetWaylandDisplay())
|
||||||
.nwh(GLFWNativeWayland.glfwGetWaylandWindow(identifier));
|
.nwh(GLFWNativeWayland.glfwGetWaylandWindow(internalWindowIdentifier));
|
||||||
case GLFW_PLATFORM_WIN32 -> init
|
case GLFW_PLATFORM_WIN32 -> init
|
||||||
.platformData()
|
.platformData()
|
||||||
.nwh(GLFWNativeWin32.glfwGetWin32Window(identifier));
|
.nwh(GLFWNativeWin32.glfwGetWin32Window(internalWindowIdentifier));
|
||||||
case GLFW_PLATFORM_COCOA -> init
|
case GLFW_PLATFORM_COCOA -> init
|
||||||
.platformData()
|
.platformData()
|
||||||
.nwh(GLFWNativeCocoa.glfwGetCocoaWindow(identifier));
|
.nwh(GLFWNativeCocoa.glfwGetCocoaWindow(internalWindowIdentifier));
|
||||||
case GLFW_PLATFORM_NULL -> {}
|
|
||||||
default -> Logger.crash("Invalid GLFW platform \"" + glfwGetPlatform() + "\"");
|
default -> Logger.crash("Invalid GLFW platform \"" + glfwGetPlatform() + "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,8 +644,6 @@ public final class Window implements AutoCloseable {
|
||||||
Logger.crash("Unable to initialize bgfx");
|
Logger.crash("Unable to initialize bgfx");
|
||||||
|
|
||||||
bgfx_set_debug(BGFX_DEBUG_TEXT);
|
bgfx_set_debug(BGFX_DEBUG_TEXT);
|
||||||
bgfx_set_view_rect(0, 0, 0, size.getX(), size.getY());
|
|
||||||
bgfx_touch(0);
|
|
||||||
} catch (UnsatisfiedLinkError error) {
|
} catch (UnsatisfiedLinkError error) {
|
||||||
Logger.crash("Failed to load LWJGL native libraries", error);
|
Logger.crash("Failed to load LWJGL native libraries", error);
|
||||||
}
|
}
|
||||||
|
@ -613,7 +660,7 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void updateState() throws NotOnMainThreadException {
|
public void updateState() throws NotOnMainThreadException {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Ensure running on the main thread
|
// Ensure running on the main thread
|
||||||
|
@ -621,14 +668,14 @@ public final class Window implements AutoCloseable {
|
||||||
throw new NotOnMainThreadException();
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
// Update window mode
|
// Update window mode
|
||||||
if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_ICONIFIED)))
|
if (TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_ICONIFIED)))
|
||||||
setWindowMode(WindowMode.MINIMIZED);
|
mode = Mode.MINIMIZED;
|
||||||
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_MAXIMIZED)))
|
else if (TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_MAXIMIZED)))
|
||||||
setWindowMode(WindowMode.MAXIMIZED);
|
mode = Mode.MAXIMIZED;
|
||||||
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_VISIBLE)))
|
else if (TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_VISIBLE)))
|
||||||
setWindowMode(WindowMode.WINDOWED);
|
mode = Mode.WINDOWED;
|
||||||
else if (Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_VISIBLE)))
|
else if (TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_VISIBLE)))
|
||||||
setWindowMode(WindowMode.HIDDEN);
|
mode = Mode.HIDDEN;
|
||||||
|
|
||||||
// Update monitor
|
// Update monitor
|
||||||
if (!getMonitor().isConnected()) {
|
if (!getMonitor().isConnected()) {
|
||||||
|
@ -638,10 +685,12 @@ public final class Window implements AutoCloseable {
|
||||||
if (monitor.isConnected())
|
if (monitor.isConnected())
|
||||||
newMonitor = monitor;
|
newMonitor = monitor;
|
||||||
|
|
||||||
if (newMonitor == null)
|
if (newMonitor == null) {
|
||||||
Logger.crash("Unable to set a new target monitor for window " + getUniqueIdentifier() + " as no monitors are connected to the system");
|
Logger.crash("Unable to set a new target monitor for window " + getUniqueIdentifier() + " as no monitors are connected to the system");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setMonitor(Objects.requireNonNull(newMonitor));
|
monitor = newMonitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update vectors
|
// Update vectors
|
||||||
|
@ -649,17 +698,17 @@ public final class Window implements AutoCloseable {
|
||||||
IntBuffer width = stack.mallocInt(2);
|
IntBuffer width = stack.mallocInt(2);
|
||||||
IntBuffer height = stack.mallocInt(2);
|
IntBuffer height = stack.mallocInt(2);
|
||||||
|
|
||||||
glfwGetWindowSize(identifier, width, height);
|
glfwGetWindowSize(internalWindowIdentifier, width, height);
|
||||||
setSize(new Vec2i(width.get(), height.get()));
|
size = new Vec2i(width.get(), height.get());
|
||||||
|
|
||||||
glfwGetWindowPos(identifier, width, height);
|
glfwGetWindowPos(internalWindowIdentifier, width, height);
|
||||||
setPosition(new Vec2i(width.get(), height.get()));
|
position = new Vec2i(width.get(), height.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update booleans
|
// Update booleans
|
||||||
setResizable(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_RESIZABLE)));
|
resizable = TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_RESIZABLE));
|
||||||
setOnTop(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_FLOATING)));
|
onTop = TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_FLOATING));
|
||||||
setTransparent(Miscellaneous.getBooleanizedInteger(glfwGetWindowAttrib(identifier, GLFW_TRANSPARENT_FRAMEBUFFER)));
|
transparent = TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_TRANSPARENT_FRAMEBUFFER));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -672,18 +721,15 @@ public final class Window implements AutoCloseable {
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public void render() throws NotOnMainThreadException {
|
public void render() throws NotOnMainThreadException {
|
||||||
// Ensure running on the main thread
|
|
||||||
if (!Miscellaneous.onMainThread())
|
|
||||||
throw new NotOnMainThreadException();
|
|
||||||
|
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Ensure rendering is enabled
|
// Ensure rendering is enabled
|
||||||
if (!isRendering())
|
if (!isRendering())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glfwSwapBuffers(identifier);
|
bgfx_set_view_rect(0, 0, 0, size.getX(), size.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -696,8 +742,13 @@ public final class Window implements AutoCloseable {
|
||||||
if (!Miscellaneous.onMainThread())
|
if (!Miscellaneous.onMainThread())
|
||||||
throw new NotOnMainThreadException();
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
closeInternal();
|
// Ensure the window is not terminated
|
||||||
|
if (terminated)
|
||||||
|
return;
|
||||||
|
|
||||||
|
windows.remove(this);
|
||||||
terminated = true;
|
terminated = true;
|
||||||
|
closeInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -709,11 +760,12 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
private void closeInternal() {
|
private void closeInternal() {
|
||||||
// Terminate bgfx
|
// Terminate bgfx
|
||||||
bgfx_shutdown();
|
if (glfwGetPlatform() != GLFW_PLATFORM_NULL)
|
||||||
|
bgfx_shutdown();
|
||||||
|
|
||||||
// Destroy the window
|
// Destroy the window
|
||||||
Callbacks.glfwFreeCallbacks(identifier);
|
Callbacks.glfwFreeCallbacks(internalWindowIdentifier);
|
||||||
glfwDestroyWindow(identifier);
|
glfwDestroyWindow(internalWindowIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -724,11 +776,15 @@ public final class Window implements AutoCloseable {
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public boolean isClosureRequested() {
|
public boolean isClosureRequested() {
|
||||||
|
// Ensure running on the main thread
|
||||||
|
if (!Miscellaneous.onMainThread())
|
||||||
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return glfwWindowShouldClose(identifier);
|
return glfwWindowShouldClose(internalWindowIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -738,11 +794,15 @@ public final class Window implements AutoCloseable {
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public boolean isFocused() {
|
public boolean isFocused() {
|
||||||
|
// Ensure running on the main thread
|
||||||
|
if (!Miscellaneous.onMainThread())
|
||||||
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Miscellaneous.getTristatedInteger(glfwGetWindowAttrib(identifier, GLFW_FOCUSED)).toBoolean();
|
return TypeConversion.integerToBoolean(glfwGetWindowAttrib(internalWindowIdentifier, GLFW_FOCUSED));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -752,11 +812,15 @@ public final class Window implements AutoCloseable {
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public void focus() {
|
public void focus() {
|
||||||
|
// Ensure running on the main thread
|
||||||
|
if (!Miscellaneous.onMainThread())
|
||||||
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glfwFocusWindow(identifier);
|
glfwFocusWindow(internalWindowIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -770,11 +834,15 @@ public final class Window implements AutoCloseable {
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public void requestAttention() {
|
public void requestAttention() {
|
||||||
|
// Ensure running on the main thread
|
||||||
|
if (!Miscellaneous.onMainThread())
|
||||||
|
throw new NotOnMainThreadException();
|
||||||
|
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glfwRequestWindowAttention(identifier);
|
glfwRequestWindowAttention(internalWindowIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----> Setters & getters
|
// -----> Setters & getters
|
||||||
|
@ -801,7 +869,7 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setName(@NotNull String name) {
|
public void setName(@NotNull String name) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -816,11 +884,11 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setTitle(@NotNull String title) {
|
public void setTitle(@NotNull String title) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.title = title;
|
this.title = title;
|
||||||
glfwSetWindowTitle(identifier, title);
|
glfwSetWindowTitle(internalWindowIdentifier, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -833,7 +901,7 @@ public final class Window implements AutoCloseable {
|
||||||
@ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
public void setIcons(@NotNull Path @Nullable [] icons) {
|
public void setIcons(@NotNull Path @Nullable [] icons) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.icons = icons;
|
this.icons = icons;
|
||||||
|
@ -873,7 +941,7 @@ public final class Window implements AutoCloseable {
|
||||||
iconsBuffer.position(0);
|
iconsBuffer.position(0);
|
||||||
Logger.diag("setting icons");
|
Logger.diag("setting icons");
|
||||||
Logger.flush();
|
Logger.flush();
|
||||||
glfwSetWindowIcon(identifier, iconsBuffer);
|
glfwSetWindowIcon(internalWindowIdentifier, iconsBuffer);
|
||||||
|
|
||||||
// Free icons
|
// Free icons
|
||||||
Logger.diag("freeing icons");
|
Logger.diag("freeing icons");
|
||||||
|
@ -894,11 +962,11 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setSize(@NotNull Vec2i size) {
|
public void setSize(@NotNull Vec2i size) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.size = size;
|
this.size = size;
|
||||||
glfwSetWindowSize(identifier, size.getX(), size.getY());
|
glfwSetWindowSize(internalWindowIdentifier, size.getX(), size.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -911,11 +979,11 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setMinimumSize(@NotNull Vec2i minimumSize) {
|
public void setMinimumSize(@NotNull Vec2i minimumSize) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.minimumSize = minimumSize;
|
this.minimumSize = minimumSize;
|
||||||
glfwSetWindowSizeLimits(identifier, minimumSize.getX(), minimumSize.getY(), getMaximumSize().getX(), getMaximumSize().getY());
|
glfwSetWindowSizeLimits(internalWindowIdentifier, minimumSize.getX(), minimumSize.getY(), getMaximumSize().getX(), getMaximumSize().getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -928,11 +996,11 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setMaximumSize(@NotNull Vec2i maximumSize) {
|
public void setMaximumSize(@NotNull Vec2i maximumSize) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.maximumSize = maximumSize;
|
this.maximumSize = maximumSize;
|
||||||
glfwSetWindowSizeLimits(identifier, getMinimumSize().getX(), getMinimumSize().getY(), maximumSize.getX(), maximumSize.getY());
|
glfwSetWindowSizeLimits(internalWindowIdentifier, getMinimumSize().getX(), getMinimumSize().getY(), maximumSize.getX(), maximumSize.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -943,49 +1011,50 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setPosition(@NotNull Vec2i position) {
|
public void setPosition(@NotNull Vec2i position) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (isTerminated() || !RenderingSubsystemConfiguration.getInstance().isDebugAllowPositionUpdates())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.position = position;
|
this.position = position;
|
||||||
glfwSetWindowSize(identifier, position.getX(), position.getY());
|
glfwSetWindowSize(internalWindowIdentifier, position.getX(), position.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the window mode.
|
* Sets the window mode.
|
||||||
*
|
*
|
||||||
* @param windowMode new mode
|
* @param mode new mode
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public void setWindowMode(@NotNull WindowMode windowMode) {
|
public void setMode(@NotNull Window.Mode mode) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.windowMode = windowMode;
|
this.mode = mode;
|
||||||
switch (windowMode) {
|
switch (mode) {
|
||||||
case HIDDEN -> glfwHideWindow(identifier);
|
case HIDDEN -> glfwHideWindow(internalWindowIdentifier);
|
||||||
case WINDOWED -> {
|
case WINDOWED -> {
|
||||||
glfwShowWindow(identifier);
|
glfwShowWindow(internalWindowIdentifier);
|
||||||
glfwRestoreWindow(identifier);
|
glfwRestoreWindow(internalWindowIdentifier);
|
||||||
}
|
}
|
||||||
case MINIMIZED -> {
|
case MINIMIZED -> {
|
||||||
glfwShowWindow(identifier);
|
glfwShowWindow(internalWindowIdentifier);
|
||||||
glfwIconifyWindow(identifier);
|
glfwIconifyWindow(internalWindowIdentifier);
|
||||||
}
|
}
|
||||||
case MAXIMIZED -> {
|
case MAXIMIZED -> {
|
||||||
glfwShowWindow(identifier);
|
glfwShowWindow(internalWindowIdentifier);
|
||||||
glfwRestoreWindow(identifier);
|
glfwRestoreWindow(internalWindowIdentifier);
|
||||||
glfwMaximizeWindow(identifier);
|
glfwMaximizeWindow(internalWindowIdentifier);
|
||||||
}
|
}
|
||||||
case BORDERLESS_FULLSCREEN -> {
|
case BORDERLESS_FULLSCREEN -> {
|
||||||
glfwShowWindow(identifier);
|
glfwShowWindow(internalWindowIdentifier);
|
||||||
glfwRestoreWindow(identifier);
|
glfwRestoreWindow(internalWindowIdentifier);
|
||||||
|
glfwSetWindowPos(internalWindowIdentifier, 0, 0);
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
case EXCLUSIVE_FULLSCREEN -> {
|
case EXCLUSIVE_FULLSCREEN -> {
|
||||||
glfwShowWindow(identifier);
|
glfwShowWindow(internalWindowIdentifier);
|
||||||
glfwRestoreWindow(identifier);
|
glfwRestoreWindow(internalWindowIdentifier);
|
||||||
// TODO
|
glfwSetWindowPos(internalWindowIdentifier, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -998,7 +1067,7 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setResizable(boolean resizable) {
|
public void setResizable(boolean resizable) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.resizable = resizable;
|
this.resizable = resizable;
|
||||||
|
@ -1012,7 +1081,7 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setBorderless(boolean borderless) {
|
public void setBorderless(boolean borderless) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.borderless = borderless;
|
this.borderless = borderless;
|
||||||
|
@ -1026,7 +1095,7 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setFocusable(boolean focusable) {
|
public void setFocusable(boolean focusable) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.focusable = focusable;
|
this.focusable = focusable;
|
||||||
|
@ -1040,7 +1109,7 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setOnTop(boolean onTop) {
|
public void setOnTop(boolean onTop) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.onTop = onTop;
|
this.onTop = onTop;
|
||||||
|
@ -1057,14 +1126,79 @@ public final class Window implements AutoCloseable {
|
||||||
*/
|
*/
|
||||||
public void setTransparent(boolean transparent) {
|
public void setTransparent(boolean transparent) {
|
||||||
// Ensure the window is not terminated
|
// Ensure the window is not terminated
|
||||||
if (isTerminated())
|
if (terminated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.transparent = transparent;
|
this.transparent = transparent;
|
||||||
initializeWindow();
|
initializeWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----> Builder inner class
|
// -----> Inner classes
|
||||||
|
/**
|
||||||
|
* How a window can be displayed.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
public enum Mode {
|
||||||
|
/**
|
||||||
|
* Marks the window as hidden, making it invisible and unable to be interacted with.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
HIDDEN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks the window as windowed, which
|
||||||
|
* will allow the user to drag around the window freely.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
WINDOWED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #HIDDEN} mode, but the window can be
|
||||||
|
* summoned back into {@link #WINDOWED} mode by the user
|
||||||
|
* by (for example) clicking an icon or {@code ALT+TAB}-ing.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
MINIMIZED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link #WINDOWED}, but will make the window occupy
|
||||||
|
* most of the screen space, except for windows/bars/docks.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
MAXIMIZED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the window will have the same
|
||||||
|
* size as the monitor it is currently on.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
BORDERLESS_FULLSCREEN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the window occupy the entire
|
||||||
|
* monitor it is currently on without
|
||||||
|
* allowing other windows to occupy
|
||||||
|
* the same space.
|
||||||
|
* <p>
|
||||||
|
* This will increase rendering
|
||||||
|
* throughput as the window manager
|
||||||
|
* or compositor does not need to
|
||||||
|
* care about other windows occupying
|
||||||
|
* the same monitor. Use (and recommend)
|
||||||
|
* this mode if you/your users
|
||||||
|
* want more frames per second.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
EXCLUSIVE_FULLSCREEN
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides an API for building {@link Window}s more easily.
|
* Provides an API for building {@link Window}s more easily.
|
||||||
*
|
*
|
||||||
|
@ -1131,10 +1265,10 @@ public final class Window implements AutoCloseable {
|
||||||
/**
|
/**
|
||||||
* Contains the window mode.
|
* Contains the window mode.
|
||||||
*
|
*
|
||||||
* @see Window#windowMode
|
* @see Window#mode
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
private @Nullable WindowMode windowMode = null;
|
private @Nullable Window.Mode mode = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the target monitor.
|
* Contains the target monitor.
|
||||||
|
@ -1235,8 +1369,8 @@ public final class Window implements AutoCloseable {
|
||||||
minimumSize = new Vec2i(-1, -1);
|
minimumSize = new Vec2i(-1, -1);
|
||||||
if (maximumSize == null)
|
if (maximumSize == null)
|
||||||
maximumSize = new Vec2i(-1, -1);
|
maximumSize = new Vec2i(-1, -1);
|
||||||
if (windowMode == null)
|
if (mode == null)
|
||||||
windowMode = WindowMode.WINDOWED;
|
mode = Mode.WINDOWED;
|
||||||
if (monitor == null)
|
if (monitor == null)
|
||||||
monitor = Monitor.getMonitors().getFirst();
|
monitor = Monitor.getMonitors().getFirst();
|
||||||
|
|
||||||
|
@ -1255,7 +1389,7 @@ public final class Window implements AutoCloseable {
|
||||||
renderingBoolean = false;
|
renderingBoolean = false;
|
||||||
|
|
||||||
// Create new Window instance
|
// Create new Window instance
|
||||||
return new Window(name, title, icons, size, minimumSize, maximumSize, position, windowMode, monitor, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean);
|
return new Window(name, title, icons, size, minimumSize, maximumSize, position, mode, monitor, resizableBoolean, borderlessBoolean, focusableBoolean, onTopBoolean, transparentBoolean, renderingBoolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1340,11 +1474,11 @@ public final class Window implements AutoCloseable {
|
||||||
* Returns the window mode.
|
* Returns the window mode.
|
||||||
*
|
*
|
||||||
* @return window mode
|
* @return window mode
|
||||||
* @see Window#windowMode
|
* @see Window#mode
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public @Nullable WindowMode getWindowMode() {
|
public @Nullable Window.Mode getWindowMode() {
|
||||||
return windowMode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1519,13 +1653,13 @@ public final class Window implements AutoCloseable {
|
||||||
/**
|
/**
|
||||||
* Sets the window mode.
|
* Sets the window mode.
|
||||||
*
|
*
|
||||||
* @param windowMode new window mode
|
* @param mode new window mode
|
||||||
* @return builder instance
|
* @return builder instance
|
||||||
* @see Window#windowMode
|
* @see Window#mode
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public @NotNull Builder setWindowMode(@Nullable WindowMode windowMode) {
|
public @NotNull Builder setWindowMode(@Nullable Window.Mode mode) {
|
||||||
this.windowMode = windowMode;
|
this.mode = mode;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,66 +20,57 @@
|
||||||
package de.staropensource.engine.rendering.type.window;
|
package de.staropensource.engine.rendering.type.window;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains how a window should be displayed.
|
* Represents all available rendering adapters.
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public enum WindowMode {
|
public enum RenderingAdapter {
|
||||||
/**
|
/**
|
||||||
* Marks the window as hidden, making it invisible and unable to be interacted with.
|
* Allows the bgfx to autodetect the adapter to use.
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
HIDDEN,
|
ANY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the window as windowed, which
|
* Tells bgfx to use the CPU for rendering.
|
||||||
* will allow the user to drag around the window freely.
|
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
WINDOWED,
|
SOFTWARE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #HIDDEN} mode, but the window can be
|
* Tells bgfx to use AMD graphics cards for rendering.
|
||||||
* summoned back into {@link #WINDOWED} mode by the user
|
|
||||||
* by (for example) clicking an icon or {@code ALT+TAB}-ing.
|
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
MINIMIZED,
|
AMD,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as {@link #WINDOWED}, but will make the window occupy
|
* Tells bgfx to use Apple's SOC for rendering.
|
||||||
* most of the screen space, except for windows/bars/docks.
|
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
MAXIMIZED,
|
APPLE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the window will have the same
|
* Tells bgfx to use Intel graphics cards for rendering.
|
||||||
* size as the monitor it is currently on.
|
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
BORDERLESS_FULLSCREEN,
|
INTEL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes the window occupy the entire
|
* Tells bgfx to use NVIDIA graphics cards for rendering.
|
||||||
* monitor it is currently on without
|
|
||||||
* allowing other windows to occupy
|
|
||||||
* the same space.
|
|
||||||
* <p>
|
|
||||||
* This will increase rendering
|
|
||||||
* throughput as the window manager
|
|
||||||
* or compositor does not need to
|
|
||||||
* care about other windows occupying
|
|
||||||
* the same monitor. Use (and recommend)
|
|
||||||
* this mode if you/your users
|
|
||||||
* want more frames per second.
|
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
EXCLUSIVE_FULLSCREEN
|
NVIDIA,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells bgfx to use Windows' integrated graphics driver for rendering.
|
||||||
|
*
|
||||||
|
* @since v1-alpha9
|
||||||
|
*/
|
||||||
|
MICROSOFT,
|
||||||
}
|
}
|
|
@ -20,13 +20,13 @@
|
||||||
package de.staropensource.engine.rendering.type.window;
|
package de.staropensource.engine.rendering.type.window;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents all available platforms.
|
* Represents all available rendering platforms.
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
public enum RenderingPlatform {
|
public enum RenderingPlatform {
|
||||||
/**
|
/**
|
||||||
* Allows the subsystem to autodetect the platform to use.
|
* Allows GLFW to autodetect the platform to use.
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
|
@ -61,7 +61,7 @@ public enum RenderingPlatform {
|
||||||
COCOA,
|
COCOA,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefer initializing without any platform.
|
* Prefer initializing headless.
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -42,5 +42,10 @@ public enum VsyncMode {
|
||||||
*
|
*
|
||||||
* @since v1-alpha9
|
* @since v1-alpha9
|
||||||
*/
|
*/
|
||||||
ON
|
ON,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Party
|
||||||
|
*/
|
||||||
|
PARTY
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,13 @@ module sosengine.rendering {
|
||||||
requires org.lwjgl.stb;
|
requires org.lwjgl.stb;
|
||||||
requires org.lwjgl.glfw;
|
requires org.lwjgl.glfw;
|
||||||
requires org.lwjgl.bgfx;
|
requires org.lwjgl.bgfx;
|
||||||
|
requires java.desktop;
|
||||||
|
|
||||||
// API access
|
// API access
|
||||||
exports de.staropensource.engine.rendering;
|
exports de.staropensource.engine.rendering;
|
||||||
exports de.staropensource.engine.rendering.event;
|
exports de.staropensource.engine.rendering.event;
|
||||||
exports de.staropensource.engine.rendering.exception;
|
exports de.staropensource.engine.rendering.exception;
|
||||||
|
exports de.staropensource.engine.rendering.renderer;
|
||||||
exports de.staropensource.engine.rendering.type;
|
exports de.staropensource.engine.rendering.type;
|
||||||
exports de.staropensource.engine.rendering.type.input;
|
exports de.staropensource.engine.rendering.type.input;
|
||||||
exports de.staropensource.engine.rendering.type.window;
|
exports de.staropensource.engine.rendering.type.window;
|
||||||
|
@ -27,6 +29,7 @@ module sosengine.rendering {
|
||||||
opens de.staropensource.engine.rendering;
|
opens de.staropensource.engine.rendering;
|
||||||
opens de.staropensource.engine.rendering.event;
|
opens de.staropensource.engine.rendering.event;
|
||||||
opens de.staropensource.engine.rendering.exception;
|
opens de.staropensource.engine.rendering.exception;
|
||||||
|
opens de.staropensource.engine.rendering.renderer;
|
||||||
opens de.staropensource.engine.rendering.type;
|
opens de.staropensource.engine.rendering.type;
|
||||||
opens de.staropensource.engine.rendering.type.input;
|
opens de.staropensource.engine.rendering.type.input;
|
||||||
opens de.staropensource.engine.rendering.type.window;
|
opens de.staropensource.engine.rendering.type.window;
|
||||||
|
|
|
@ -25,9 +25,9 @@ import de.staropensource.engine.base.implementable.EventListenerCode;
|
||||||
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
import de.staropensource.engine.base.implementable.helper.EventHelper;
|
||||||
import de.staropensource.engine.base.logging.Logger;
|
import de.staropensource.engine.base.logging.Logger;
|
||||||
import de.staropensource.engine.base.type.vector.Vec2i;
|
import de.staropensource.engine.base.type.vector.Vec2i;
|
||||||
import de.staropensource.engine.base.utility.misc.Miscellaneous;
|
|
||||||
import de.staropensource.engine.rendering.RenderingSubsystem;
|
|
||||||
import de.staropensource.engine.rendering.event.InputEvent;
|
import de.staropensource.engine.rendering.event.InputEvent;
|
||||||
|
import de.staropensource.engine.rendering.renderer.Renderer;
|
||||||
|
import de.staropensource.engine.rendering.type.FrameHandler;
|
||||||
import de.staropensource.engine.rendering.type.Window;
|
import de.staropensource.engine.rendering.type.Window;
|
||||||
import de.staropensource.engine.rendering.type.input.Key;
|
import de.staropensource.engine.rendering.type.input.Key;
|
||||||
import de.staropensource.engine.rendering.type.input.KeyState;
|
import de.staropensource.engine.rendering.type.input.KeyState;
|
||||||
|
@ -35,8 +35,6 @@ import lombok.Getter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main class of the sos!engine development application.
|
* The main class of the sos!engine development application.
|
||||||
*
|
*
|
||||||
|
@ -140,14 +138,23 @@ public final class Main {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render loop
|
// Add frame handlers
|
||||||
LinkedHashMap<@NotNull Window, @NotNull Throwable> renderLoopFailures = RenderingSubsystem
|
Renderer.addFrameHandler(new FrameHandler() {
|
||||||
.getInstance()
|
@Override
|
||||||
.runRenderLoop(() -> {
|
public @NotNull FrameHandler.Priority getPriority() {
|
||||||
if (shutdown || window.isClosureRequested())
|
return Priority.DEFAULT;
|
||||||
Engine.getInstance().shutdown();
|
}
|
||||||
});
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (shutdown || window.isClosureRequested())
|
||||||
|
Engine.getInstance().shutdown();
|
||||||
|
|
||||||
|
//window.setPosition(new Vec2i((int) Renderer.getFrameCount() / 10, (int) Renderer.getFrameCount() / 10));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start renderer
|
||||||
|
Renderer.start();
|
||||||
} catch (Exception exception) {
|
} catch (Exception exception) {
|
||||||
Logger.crash("Caught throwable in main thread:", exception);
|
Logger.crash("Caught throwable in main thread:", exception);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue