Renderer full life cycle;
This commit is contained in:
@@ -12,6 +12,8 @@ public interface Renderer {
|
||||
|
||||
void reset();
|
||||
|
||||
void shutdown();
|
||||
|
||||
void takeScreenshot();
|
||||
|
||||
void setTitle(final String title);
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.function.Consumer;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import de.extio.game_engine.renderer.model.RenderingBo;
|
||||
@@ -32,8 +33,8 @@ public class RendererConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RendererData rendererData(final Renderer renderer, final RendererControl rendererControl, final RenderingBoPool renderingBoPool, @Qualifier("gameEngineEventConsumer") final Consumer<Object> eventConsumer) {
|
||||
final var rendererData = new RendererData(renderer, rendererControl, renderingBoPool, eventConsumer);
|
||||
public RendererData rendererData(final ApplicationContext applicationContext, final Renderer renderer, final RendererControl rendererControl, final RenderingBoPool renderingBoPool, @Qualifier("gameEngineEventConsumer") final Consumer<Object> eventConsumer) {
|
||||
final var rendererData = new RendererData(applicationContext, renderer, rendererControl, renderingBoPool, eventConsumer);
|
||||
renderer.setRendererData(rendererData);
|
||||
rendererControl.setRendererData(rendererData);
|
||||
renderingBoPool.setRendererData(rendererData);
|
||||
@@ -41,11 +42,8 @@ public class RendererConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RendererLoop rendererLoop(final RendererData rendererData) {
|
||||
final var rendererLoop = new RendererLoop(rendererData);
|
||||
rendererData.setRendererLoop(rendererLoop);
|
||||
rendererLoop.start();
|
||||
return rendererLoop;
|
||||
public RendererLauncher rendererLauncher(final ApplicationContext applicationContext, final RendererData rendererData) {
|
||||
return new RendererLauncher(applicationContext, rendererData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,11 +3,15 @@ package de.extio.game_engine.renderer;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import de.extio.game_engine.renderer.model.options.UiOptions;
|
||||
import de.extio.game_engine.renderer.model.options.VideoOptions;
|
||||
|
||||
public class RendererData {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
private final Renderer renderer;
|
||||
|
||||
private final RendererControl rendererControl;
|
||||
@@ -24,13 +28,18 @@ public class RendererData {
|
||||
|
||||
private RendererLoop rendererLoop;
|
||||
|
||||
public RendererData(final Renderer renderer, final RendererControl rendererControl, final RenderingBoPool renderingBoPool, final Consumer<Object> eventConsumer) {
|
||||
public RendererData(final ApplicationContext applicationContext, final Renderer renderer, final RendererControl rendererControl, final RenderingBoPool renderingBoPool, final Consumer<Object> eventConsumer) {
|
||||
this.applicationContext = applicationContext;
|
||||
this.renderer = renderer;
|
||||
this.rendererControl = rendererControl;
|
||||
this.renderingBoPool = renderingBoPool;
|
||||
this.eventConsumer = eventConsumer;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
public RendererControl getRendererControl() {
|
||||
return this.rendererControl;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
package de.extio.game_engine.renderer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class RendererLauncher implements InitializingBean, DisposableBean {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RendererLauncher.class);
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
private final RendererData rendererData;
|
||||
|
||||
private RendererLoop rendererLoop;
|
||||
|
||||
private Thread rendererLoopThread;
|
||||
|
||||
private Thread watchDogThread;
|
||||
|
||||
public RendererLauncher(final ApplicationContext applicationContext, final RendererData rendererData) {
|
||||
this.applicationContext = applicationContext;
|
||||
this.rendererData = rendererData;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void start() {
|
||||
// this.launch();
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.launch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
this.shutdown();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void stop() {
|
||||
// this.shutdown();
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// public boolean isRunning() {
|
||||
// return this.rendererLoopThread != null && this.rendererLoopThread.isAlive();
|
||||
// }
|
||||
|
||||
private void launch() {
|
||||
if (this.rendererLoopThread != null && this.rendererLoopThread.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Launching RendererLoop");
|
||||
this.rendererLoop = new RendererLoop(this.rendererData);
|
||||
rendererData.setRendererLoop(rendererLoop);
|
||||
this.rendererLoopThread = Thread.ofPlatform()
|
||||
.name("RendererLoop")
|
||||
.daemon(false)
|
||||
.start(this.rendererLoop);
|
||||
|
||||
LOGGER.info("Launching RendererWatchDog");
|
||||
this.watchDogThread = Thread.ofPlatform()
|
||||
.name("RendererWatchDog")
|
||||
.daemon(true)
|
||||
.start(() -> {
|
||||
try {
|
||||
this.rendererLoopThread.join();
|
||||
LOGGER.error("RendererLoop thread has exited unexpectedly, shutting down application");
|
||||
SpringApplication.exit(this.applicationContext, () -> 1);
|
||||
}
|
||||
catch (final InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void shutdown() {
|
||||
if (this.watchDogThread != null && this.watchDogThread.isAlive()) {
|
||||
LOGGER.info("Shutting down RendererWatchDog");
|
||||
this.watchDogThread.interrupt();
|
||||
try {
|
||||
this.watchDogThread.join(5000);
|
||||
}
|
||||
catch (final InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
this.watchDogThread = null;
|
||||
|
||||
if (this.rendererLoopThread != null && this.rendererLoopThread.isAlive() && this.rendererLoop != null) {
|
||||
LOGGER.info("Shutting down RendererLoop");
|
||||
this.rendererLoop.shutdown();
|
||||
try {
|
||||
this.rendererLoopThread.join(5000);
|
||||
}
|
||||
catch (final InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
this.rendererLoopThread = null;
|
||||
this.rendererLoop = null;
|
||||
this.rendererData.setRendererLoop(null);
|
||||
|
||||
this.rendererData.getRenderer().shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,28 +5,28 @@ import java.util.ArrayList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RendererLoop extends Thread {
|
||||
public class RendererLoop implements Runnable {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RendererLoop.class);
|
||||
|
||||
private final RendererData rendererData;
|
||||
private volatile boolean shutdown;
|
||||
|
||||
private volatile boolean running = true;
|
||||
private final RendererData rendererData;
|
||||
|
||||
public RendererLoop(final RendererData rendererData) {
|
||||
this.rendererData = rendererData;
|
||||
this.setName("Renderer-Loop");
|
||||
this.setDaemon(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
this.shutdown = false;
|
||||
|
||||
try {
|
||||
this.rendererData.getRenderer().show();
|
||||
|
||||
LOGGER.info("Renderer loop started");
|
||||
int exceptionCount = 0;
|
||||
while (this.running) {
|
||||
while (!this.shutdown) {
|
||||
try {
|
||||
this.rendererData.nextFrame();
|
||||
this.rendererData.getRenderer().run(new ArrayList<>()); // TODO: Pass actual renderables
|
||||
@@ -54,7 +54,8 @@ public class RendererLoop extends Thread {
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
this.running = false;
|
||||
LOGGER.info("RendererLoop shutdown requested");
|
||||
this.shutdown = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import javax.imageio.ImageIO;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
|
||||
import de.extio.game_engine.keyboard.KeyModifiers;
|
||||
import de.extio.game_engine.renderer.RendererControl;
|
||||
@@ -93,7 +94,8 @@ public class G2DMainFrame extends Frame {
|
||||
|
||||
@Override
|
||||
public void windowClosing(final WindowEvent e) {
|
||||
G2DMainFrame.this.rendererData.getRendererLoop().shutdown();
|
||||
LOGGER.info("Window closing requested");
|
||||
SpringApplication.exit(G2DMainFrame.this.rendererData.getApplicationContext(), () -> 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -99,6 +99,25 @@ public class G2DRenderer implements Renderer {
|
||||
G2DDrawControl.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
LOGGER.info("shutdown()");
|
||||
|
||||
this.rwLock.writeLock().lock();
|
||||
try {
|
||||
if (this.mainFrame != null) {
|
||||
this.mainFrame.unregisterFullScreenWindow();
|
||||
this.reset();
|
||||
this.mainFrame.setVisible(false);
|
||||
this.mainFrame.dispose();
|
||||
this.mainFrame = null;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
this.rwLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final List<RenderingBo> renderingBOs) throws InterruptedException {
|
||||
try {
|
||||
|
||||
@@ -163,8 +163,11 @@ public class G2DRendererControl implements RendererControl {
|
||||
if (this.updateAbsoluteViewportPortDimension()) {
|
||||
this.recalculate();
|
||||
}
|
||||
this.renderer.getMainFrame().createBufferStrategy();
|
||||
this.renderer.getMainFrame().resizeListenerEnabled = true;
|
||||
final var mainFrame = this.renderer.getMainFrame();
|
||||
if (mainFrame != null) {
|
||||
mainFrame.createBufferStrategy();
|
||||
mainFrame.resizeListenerEnabled = true;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (lockRenderer) {
|
||||
@@ -174,7 +177,10 @@ public class G2DRendererControl implements RendererControl {
|
||||
};
|
||||
|
||||
if (async) {
|
||||
EventQueue.invokeLater(run);
|
||||
// EventQueue.invokeLater(run); // Using EventQueue here can clutter the AWT event queue with too many events when resizing on a system with high event rate
|
||||
Thread.ofVirtual()
|
||||
.name("G2DRendererControl-ViewportUpdater", 0)
|
||||
.start(run);
|
||||
}
|
||||
else {
|
||||
run.run();
|
||||
@@ -189,7 +195,7 @@ public class G2DRendererControl implements RendererControl {
|
||||
private boolean updateAbsoluteViewportPortDimension() {
|
||||
boolean changed = false;
|
||||
final var absoluteDim = this.absoluteViewportDimension;
|
||||
if (absoluteDim == null || absoluteDim.getX() != this.renderer.getMainFrame().getWidth() || absoluteDim.getY() != this.renderer.getMainFrame().getHeight()) {
|
||||
if (absoluteDim == null || (this.renderer.getMainFrame() != null && (absoluteDim.getX() != this.renderer.getMainFrame().getWidth() || absoluteDim.getY() != this.renderer.getMainFrame().getHeight()))) {
|
||||
this.absoluteViewportDimension = ImmutableCoordI2.create(this.renderer.getMainFrame().getWidth(), this.renderer.getMainFrame().getHeight());
|
||||
changed = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user