mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 20:31:51 +09:00
744 lines
26 KiB
Plaintext
744 lines
26 KiB
Plaintext
/*******************************************************************************
|
|
* Copyright 2011 See AUTHORS file.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
******************************************************************************/
|
|
|
|
package com.badlogic.gdx.backends.lwjgl;
|
|
|
|
import com.badlogic.gdx.Application;
|
|
import com.badlogic.gdx.Gdx;
|
|
import com.badlogic.gdx.Graphics;
|
|
import com.badlogic.gdx.graphics.Cursor.SystemCursor;
|
|
import com.badlogic.gdx.graphics.GL20;
|
|
import com.badlogic.gdx.graphics.GL30;
|
|
import com.badlogic.gdx.graphics.Pixmap;
|
|
import com.badlogic.gdx.graphics.Pixmap.Format;
|
|
import com.badlogic.gdx.graphics.glutils.GLVersion;
|
|
import com.badlogic.gdx.utils.Array;
|
|
import com.badlogic.gdx.utils.GdxRuntimeException;
|
|
import com.badlogic.gdx.utils.SharedLibraryLoader;
|
|
import org.lwjgl.LWJGLException;
|
|
import org.lwjgl.input.Mouse;
|
|
import org.lwjgl.opengl.ContextAttribs;
|
|
import org.lwjgl.opengl.Display;
|
|
import org.lwjgl.opengl.GL11;
|
|
import org.lwjgl.opengl.PixelFormat;
|
|
|
|
import java.awt.*;
|
|
import java.nio.ByteBuffer;
|
|
|
|
/** An implementation of the {@link Graphics} interface based on Lwjgl.
|
|
* @author mzechner */
|
|
public class LwjglGraphics implements Graphics {
|
|
|
|
/** The suppored OpenGL extensions */
|
|
static Array<String> extensions;
|
|
static GLVersion glVersion;
|
|
|
|
GL20 gl20;
|
|
GL30 gl30;
|
|
long frameId = -1;
|
|
float deltaTime = 0;
|
|
long frameStart = 0;
|
|
int frames = 0;
|
|
int fps;
|
|
long lastTime = System.nanoTime();
|
|
Canvas canvas;
|
|
boolean vsync = false;
|
|
boolean resize = false;
|
|
LwjglApplicationConfiguration config;
|
|
BufferFormat bufferFormat = new BufferFormat(8, 8, 8, 8, 16, 8, 0, false);
|
|
volatile boolean isContinuous = true;
|
|
volatile boolean requestRendering = false;
|
|
boolean softwareMode;
|
|
boolean usingGL30;
|
|
|
|
// deltaTime kalman filter related variables
|
|
private float kalmanEstimate = 1.0f/60.0f;
|
|
private float kalmanErrorCovariance = 1.0f;
|
|
private final float kalmanErrorRate = 0.2f; // 0.2: empirical value
|
|
private final float kalmanUpdateThreshold = 0.1f;
|
|
private final float getMagnitudeDifferenceEpsilon = 0.00001f;
|
|
|
|
LwjglGraphics (LwjglApplicationConfiguration config) {
|
|
this.config = config;
|
|
}
|
|
|
|
LwjglGraphics (Canvas canvas) {
|
|
this.config = new LwjglApplicationConfiguration();
|
|
config.width = canvas.getWidth();
|
|
config.height = canvas.getHeight();
|
|
this.canvas = canvas;
|
|
}
|
|
|
|
LwjglGraphics (Canvas canvas, LwjglApplicationConfiguration config) {
|
|
this.config = config;
|
|
this.canvas = canvas;
|
|
}
|
|
|
|
|
|
public int getHeight () {
|
|
if (canvas != null)
|
|
return Math.max(1, canvas.getHeight());
|
|
else
|
|
return (int)(Display.getHeight() * Display.getPixelScaleFactor());
|
|
}
|
|
|
|
public int getWidth () {
|
|
if (canvas != null)
|
|
return Math.max(1, canvas.getWidth());
|
|
else
|
|
return (int)(Display.getWidth() * Display.getPixelScaleFactor());
|
|
}
|
|
|
|
@Override
|
|
public int getBackBufferWidth () {
|
|
return getWidth();
|
|
}
|
|
|
|
@Override
|
|
public int getBackBufferHeight () {
|
|
return getHeight();
|
|
}
|
|
|
|
|
|
public long getFrameId () {
|
|
return frameId;
|
|
}
|
|
|
|
public float getDeltaTime () {
|
|
return kalmanEstimate;
|
|
}
|
|
|
|
private void resetDeltaSmoothingHistory() {
|
|
kalmanEstimate = 1.0f/60.0f;
|
|
kalmanErrorCovariance = 1.0f;
|
|
}
|
|
|
|
// only for a > 0 && b > 0
|
|
private float getMagnitudeDifference(float a, float b) {
|
|
if (a < getMagnitudeDifferenceEpsilon || b < getMagnitudeDifferenceEpsilon) {
|
|
return (a + b) / getMagnitudeDifferenceEpsilon;
|
|
}
|
|
|
|
if (a > b) {
|
|
return a / b;
|
|
}
|
|
else {
|
|
return b / a;
|
|
}
|
|
}
|
|
|
|
private void updateKalmanRenderDelta() {
|
|
// The problem with this kalman filter is that it assumes most simplistic situation:
|
|
// 1. the actual delta (measured delta - noise) is constant (that is, not constantly increasing or something)
|
|
// 2. everything is linear
|
|
// We may need to implement Extended Kalman Filter but what is Jacobian, I suck at maths.
|
|
//
|
|
// Instead, this implementation will reset itself when difference in magnitude between
|
|
// old and new is greater than set value.
|
|
//
|
|
// It's not perfect but it works, much better than averaging.
|
|
|
|
if (getMagnitudeDifference(deltaTime, kalmanEstimate) >= 2.0) {
|
|
resetDeltaSmoothingHistory();
|
|
}
|
|
|
|
// measurement value
|
|
float observation = deltaTime;
|
|
|
|
if (observation <= kalmanUpdateThreshold) {
|
|
// time update
|
|
float priorEstimate = kalmanEstimate;
|
|
float priorError = kalmanErrorCovariance;
|
|
|
|
// measurement update
|
|
float gain = priorError / (priorError + kalmanErrorRate);
|
|
float newEstimate = priorEstimate + gain * (observation - priorEstimate);
|
|
float newError = (1.0f - gain) * priorError;
|
|
|
|
kalmanEstimate = newEstimate;
|
|
kalmanErrorCovariance = newError;
|
|
}
|
|
}
|
|
|
|
public float getRawDeltaTime () {
|
|
return deltaTime;
|
|
}
|
|
|
|
public GraphicsType getType () {
|
|
return GraphicsType.LWJGL;
|
|
}
|
|
|
|
public GLVersion getGLVersion () {
|
|
return glVersion;
|
|
}
|
|
|
|
public boolean isGL20Available () {
|
|
return gl20 != null;
|
|
}
|
|
|
|
public GL20 getGL20 () {
|
|
return gl20;
|
|
}
|
|
|
|
@Override
|
|
public void setGL20 (GL20 gl20) {
|
|
this.gl20 = gl20;
|
|
if (gl30 == null) {
|
|
Gdx.gl = gl20;
|
|
Gdx.gl20 = gl20;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isGL30Available () {
|
|
return gl30 != null;
|
|
}
|
|
|
|
@Override
|
|
public GL30 getGL30 () {
|
|
return gl30;
|
|
}
|
|
|
|
@Override
|
|
public void setGL30 (GL30 gl30) {
|
|
this.gl30 = gl30;
|
|
if (gl30 != null) {
|
|
this.gl20 = gl30;
|
|
|
|
Gdx.gl = gl20;
|
|
Gdx.gl20 = gl20;
|
|
Gdx.gl30 = gl30;
|
|
}
|
|
}
|
|
|
|
public int getFramesPerSecond () {
|
|
return fps;
|
|
}
|
|
|
|
void updateTime () {
|
|
long time = System.nanoTime();
|
|
deltaTime = (time - lastTime) / 1000000000.0f;
|
|
lastTime = time;
|
|
|
|
if (time - frameStart >= 1000000000) {
|
|
fps = frames;
|
|
frames = 0;
|
|
frameStart = time;
|
|
}
|
|
frames++;
|
|
|
|
updateKalmanRenderDelta();
|
|
}
|
|
|
|
void setupDisplay () throws LWJGLException {
|
|
if (config.useHDPI) {
|
|
System.setProperty("org.lwjgl.opengl.Display.enableHighDPI", "true");
|
|
}
|
|
|
|
if (canvas != null) {
|
|
Display.setParent(canvas);
|
|
} else {
|
|
boolean displayCreated = false;
|
|
|
|
if(!config.fullscreen) {
|
|
displayCreated = setWindowedMode(config.width, config.height);
|
|
} else {
|
|
DisplayMode bestMode = null;
|
|
for(DisplayMode mode: getDisplayModes()) {
|
|
if(mode.width == config.width && mode.height == config.height) {
|
|
if(bestMode == null || bestMode.refreshRate < this.getDisplayMode().refreshRate) {
|
|
bestMode = mode;
|
|
}
|
|
}
|
|
}
|
|
if(bestMode == null) {
|
|
bestMode = this.getDisplayMode();
|
|
}
|
|
displayCreated = setFullscreenMode(bestMode);
|
|
}
|
|
if (!displayCreated) {
|
|
if (config.setDisplayModeCallback != null) {
|
|
config = config.setDisplayModeCallback.onFailure(config);
|
|
if (config != null) {
|
|
displayCreated = setWindowedMode(config.width, config.height);
|
|
}
|
|
}
|
|
if (!displayCreated) {
|
|
throw new GdxRuntimeException("Couldn't set display mode " + config.width + "x" + config.height + ", fullscreen: "
|
|
+ config.fullscreen);
|
|
}
|
|
}
|
|
if (config.iconPaths.size > 0) {
|
|
ByteBuffer[] icons = new ByteBuffer[config.iconPaths.size];
|
|
for (int i = 0, n = config.iconPaths.size; i < n; i++) {
|
|
Pixmap pixmap = new Pixmap(Gdx.files.getFileHandle(config.iconPaths.get(i), config.iconFileTypes.get(i)));
|
|
if (pixmap.getFormat() != Format.RGBA8888) {
|
|
Pixmap rgba = new Pixmap(pixmap.getWidth(), pixmap.getHeight(), Format.RGBA8888);
|
|
rgba.drawPixmap(pixmap, 0, 0);
|
|
pixmap.dispose();
|
|
pixmap = rgba;
|
|
}
|
|
icons[i] = ByteBuffer.allocateDirect(pixmap.getPixels().limit());
|
|
icons[i].put(pixmap.getPixels()).flip();
|
|
pixmap.dispose();
|
|
}
|
|
Display.setIcon(icons);
|
|
}
|
|
}
|
|
Display.setTitle(config.title);
|
|
Display.setResizable(config.resizable);
|
|
Display.setInitialBackground(config.initialBackgroundColor.r, config.initialBackgroundColor.g,
|
|
config.initialBackgroundColor.b);
|
|
|
|
Display.setLocation(config.x, config.y);
|
|
createDisplayPixelFormat(config.useGL30, config.gles30ContextMajorVersion, config.gles30ContextMinorVersion);
|
|
initiateGL();
|
|
}
|
|
|
|
/**
|
|
* Only needed when setupDisplay() is not called.
|
|
*/
|
|
void initiateGL() {
|
|
extractVersion();
|
|
extractExtensions();
|
|
initiateGLInstances();
|
|
}
|
|
|
|
private static void extractVersion () {
|
|
String versionString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_VERSION);
|
|
String vendorString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_VENDOR);
|
|
String rendererString = org.lwjgl.opengl.GL11.glGetString(GL11.GL_RENDERER);
|
|
glVersion = new GLVersion(Application.ApplicationType.Desktop, versionString, vendorString, rendererString);
|
|
}
|
|
|
|
private static void extractExtensions () {
|
|
extensions = new Array<String>();
|
|
if (glVersion.isVersionEqualToOrHigher(3, 2)) {
|
|
int numExtensions = GL11.glGetInteger(GL30.GL_NUM_EXTENSIONS);
|
|
for (int i = 0; i < numExtensions; ++i)
|
|
extensions.add(org.lwjgl.opengl.GL30.glGetStringi(GL20.GL_EXTENSIONS, i));
|
|
} else {
|
|
extensions.addAll(org.lwjgl.opengl.GL11.glGetString(GL20.GL_EXTENSIONS).split(" "));
|
|
}
|
|
}
|
|
|
|
/** @return whether the supported OpenGL (not ES) version is compatible with OpenGL ES 3.x. */
|
|
private static boolean fullCompatibleWithGLES3 () {
|
|
// OpenGL ES 3.0 is compatible with OpenGL 4.3 core, see http://en.wikipedia.org/wiki/OpenGL_ES#OpenGL_ES_3.0
|
|
return glVersion.isVersionEqualToOrHigher(4, 3);
|
|
}
|
|
|
|
/** @return whether the supported OpenGL (not ES) version is compatible with OpenGL ES 2.x. */
|
|
private static boolean fullCompatibleWithGLES2 () {
|
|
// OpenGL ES 2.0 is compatible with OpenGL 4.1 core
|
|
// see https://www.opengl.org/registry/specs/ARB/ES2_compatibility.txt
|
|
return glVersion.isVersionEqualToOrHigher(4, 1) || extensions.contains("GL_ARB_ES2_compatibility", false);
|
|
}
|
|
|
|
private static boolean supportsFBO () {
|
|
// FBO is in core since OpenGL 3.0, see https://www.opengl.org/wiki/Framebuffer_Object
|
|
return glVersion.isVersionEqualToOrHigher(3, 0) || extensions.contains("GL_EXT_framebuffer_object", false)
|
|
|| extensions.contains("GL_ARB_framebuffer_object", false);
|
|
}
|
|
|
|
private void createDisplayPixelFormat (boolean useGL30, int gles30ContextMajor, int gles30ContextMinor) {
|
|
try {
|
|
if (useGL30) {
|
|
ContextAttribs context = new ContextAttribs(gles30ContextMajor, gles30ContextMinor).withForwardCompatible(false)
|
|
.withProfileCore(true);
|
|
try {
|
|
Display.create(new PixelFormat(config.r + config.g + config.b, config.a, config.depth, config.stencil,
|
|
config.samples), context);
|
|
} catch (Exception e) {
|
|
System.out.println("LwjglGraphics: OpenGL " + gles30ContextMajor + "." + gles30ContextMinor
|
|
+ "+ core profile (GLES 3.0) not supported.");
|
|
createDisplayPixelFormat(false, gles30ContextMajor, gles30ContextMinor);
|
|
return;
|
|
}
|
|
System.out.println("LwjglGraphics: created OpenGL " + gles30ContextMajor + "." + gles30ContextMinor
|
|
+ "+ core profile (GLES 3.0) context. This is experimental!");
|
|
usingGL30 = true;
|
|
} else {
|
|
Display
|
|
.create(new PixelFormat(config.r + config.g + config.b, config.a, config.depth, config.stencil, config.samples));
|
|
usingGL30 = false;
|
|
}
|
|
bufferFormat = new BufferFormat(config.r, config.g, config.b, config.a, config.depth, config.stencil, config.samples,
|
|
false);
|
|
} catch (Exception ex) {
|
|
Display.destroy();
|
|
try {
|
|
Thread.sleep(200);
|
|
} catch (InterruptedException ignored) {
|
|
}
|
|
try {
|
|
Display.create(new PixelFormat(0, 16, 8));
|
|
if (getDisplayMode().bitsPerPixel == 16) {
|
|
bufferFormat = new BufferFormat(5, 6, 5, 0, 16, 8, 0, false);
|
|
}
|
|
if (getDisplayMode().bitsPerPixel == 24) {
|
|
bufferFormat = new BufferFormat(8, 8, 8, 0, 16, 8, 0, false);
|
|
}
|
|
if (getDisplayMode().bitsPerPixel == 32) {
|
|
bufferFormat = new BufferFormat(8, 8, 8, 8, 16, 8, 0, false);
|
|
}
|
|
} catch (Exception ex2) {
|
|
Display.destroy();
|
|
try {
|
|
Thread.sleep(200);
|
|
} catch (InterruptedException ignored) {
|
|
}
|
|
try {
|
|
Display.create(new PixelFormat());
|
|
} catch (Exception ex3) {
|
|
if (!softwareMode && config.allowSoftwareMode) {
|
|
softwareMode = true;
|
|
System.setProperty("org.lwjgl.opengl.Display.allowSoftwareOpenGL", "true");
|
|
createDisplayPixelFormat(useGL30, gles30ContextMajor, gles30ContextMinor);
|
|
return;
|
|
}
|
|
throw new GdxRuntimeException("OpenGL is not supported by the video driver.", ex3);
|
|
}
|
|
if (getDisplayMode().bitsPerPixel == 16) {
|
|
bufferFormat = new BufferFormat(5, 6, 5, 0, 8, 0, 0, false);
|
|
}
|
|
if (getDisplayMode().bitsPerPixel == 24) {
|
|
bufferFormat = new BufferFormat(8, 8, 8, 0, 8, 0, 0, false);
|
|
}
|
|
if (getDisplayMode().bitsPerPixel == 32) {
|
|
bufferFormat = new BufferFormat(8, 8, 8, 8, 8, 0, 0, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void initiateGLInstances () {
|
|
if (usingGL30) {
|
|
gl30 = new LwjglGL30();
|
|
gl20 = gl30;
|
|
} else {
|
|
gl20 = new LwjglGL20();
|
|
}
|
|
|
|
if (!glVersion.isVersionEqualToOrHigher(2, 0))
|
|
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
|
|
+ GL11.glGetString(GL11.GL_VERSION) + "\n" + glVersion.getDebugVersionString());
|
|
|
|
if (!supportsFBO()) {
|
|
throw new GdxRuntimeException("OpenGL 2.0 or higher with the FBO extension is required. OpenGL version: "
|
|
+ GL11.glGetString(GL11.GL_VERSION) + ", FBO extension: false\n" + glVersion.getDebugVersionString());
|
|
}
|
|
|
|
Gdx.gl = gl20;
|
|
Gdx.gl20 = gl20;
|
|
Gdx.gl30 = gl30;
|
|
}
|
|
|
|
@Override
|
|
public float getPpiX () {
|
|
return Toolkit.getDefaultToolkit().getScreenResolution();
|
|
}
|
|
|
|
@Override
|
|
public float getPpiY () {
|
|
return Toolkit.getDefaultToolkit().getScreenResolution();
|
|
}
|
|
|
|
@Override
|
|
public float getPpcX () {
|
|
return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);
|
|
}
|
|
|
|
@Override
|
|
public float getPpcY () {
|
|
return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);
|
|
}
|
|
|
|
@Override
|
|
public float getDensity () {
|
|
if (config.overrideDensity != -1) return config.overrideDensity / 160f;
|
|
return (Toolkit.getDefaultToolkit().getScreenResolution() / 160f);
|
|
}
|
|
|
|
@Override
|
|
public boolean supportsDisplayModeChange () {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Monitor getPrimaryMonitor () {
|
|
return new LwjglMonitor(0, 0, "Primary Monitor");
|
|
}
|
|
|
|
@Override
|
|
public Monitor getMonitor () {
|
|
return getPrimaryMonitor();
|
|
}
|
|
|
|
@Override
|
|
public Monitor[] getMonitors () {
|
|
return new Monitor[] { getPrimaryMonitor() };
|
|
}
|
|
|
|
@Override
|
|
public DisplayMode[] getDisplayModes (Monitor monitor) {
|
|
return getDisplayModes();
|
|
}
|
|
|
|
@Override
|
|
public DisplayMode getDisplayMode (Monitor monitor) {
|
|
return getDisplayMode();
|
|
}
|
|
|
|
@Override
|
|
public boolean setFullscreenMode (DisplayMode displayMode) {
|
|
org.lwjgl.opengl.DisplayMode mode = ((LwjglDisplayMode)displayMode).mode;
|
|
try {
|
|
if (!mode.isFullscreenCapable()) {
|
|
Display.setDisplayMode(mode);
|
|
} else {
|
|
Display.setDisplayModeAndFullscreen(mode);
|
|
}
|
|
float scaleFactor = Display.getPixelScaleFactor();
|
|
config.width = (int)(mode.getWidth() * scaleFactor);
|
|
config.height = (int)(mode.getHeight() * scaleFactor);
|
|
if (Gdx.gl != null) Gdx.gl.glViewport(0, 0, config.width, config.height);
|
|
resize = true;
|
|
return true;
|
|
} catch (LWJGLException e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/** Kindly stolen from http://lwjgl.org/wiki/index.php?title=LWJGL_Basics_5_(Fullscreen), not perfect but will do. */
|
|
@Override
|
|
public boolean setWindowedMode (int width, int height) {
|
|
if (getWidth() == width && getHeight() == height && !Display.isFullscreen()) {
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
org.lwjgl.opengl.DisplayMode targetDisplayMode = null;
|
|
boolean fullscreen = false;
|
|
|
|
if (fullscreen) {
|
|
org.lwjgl.opengl.DisplayMode[] modes = Display.getAvailableDisplayModes();
|
|
int freq = 0;
|
|
|
|
for (int i = 0; i < modes.length; i++) {
|
|
org.lwjgl.opengl.DisplayMode current = modes[i];
|
|
|
|
if ((current.getWidth() == width) && (current.getHeight() == height)) {
|
|
if ((targetDisplayMode == null) || (current.getFrequency() >= freq)) {
|
|
if ((targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel())) {
|
|
targetDisplayMode = current;
|
|
freq = targetDisplayMode.getFrequency();
|
|
}
|
|
}
|
|
|
|
// if we've found a match for bpp and frequence against the
|
|
// original display mode then it's probably best to go for this one
|
|
// since it's most likely compatible with the monitor
|
|
if ((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel())
|
|
&& (current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())) {
|
|
targetDisplayMode = current;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
targetDisplayMode = new org.lwjgl.opengl.DisplayMode(width, height);
|
|
}
|
|
|
|
if (targetDisplayMode == null) {
|
|
return false;
|
|
}
|
|
|
|
boolean resizable = !fullscreen && config.resizable;
|
|
|
|
Display.setDisplayMode(targetDisplayMode);
|
|
Display.setFullscreen(fullscreen);
|
|
// Workaround for bug in LWJGL whereby resizable state is lost on DisplayMode change
|
|
if (resizable == Display.isResizable()) {
|
|
Display.setResizable(!resizable);
|
|
}
|
|
Display.setResizable(resizable);
|
|
|
|
float scaleFactor = Display.getPixelScaleFactor();
|
|
config.width = (int)(targetDisplayMode.getWidth() * scaleFactor);
|
|
config.height = (int)(targetDisplayMode.getHeight() * scaleFactor);
|
|
if (Gdx.gl != null) Gdx.gl.glViewport(0, 0, config.width, config.height);
|
|
resize = true;
|
|
return true;
|
|
} catch (LWJGLException e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public DisplayMode[] getDisplayModes () {
|
|
try {
|
|
org.lwjgl.opengl.DisplayMode[] availableDisplayModes = Display.getAvailableDisplayModes();
|
|
DisplayMode[] modes = new DisplayMode[availableDisplayModes.length];
|
|
|
|
int idx = 0;
|
|
for (org.lwjgl.opengl.DisplayMode mode : availableDisplayModes) {
|
|
if (mode.isFullscreenCapable()) {
|
|
modes[idx++] = new LwjglDisplayMode(mode.getWidth(), mode.getHeight(), mode.getFrequency(),
|
|
mode.getBitsPerPixel(), mode);
|
|
}
|
|
}
|
|
|
|
return modes;
|
|
} catch (LWJGLException e) {
|
|
throw new GdxRuntimeException("Couldn't fetch available display modes", e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public DisplayMode getDisplayMode () {
|
|
org.lwjgl.opengl.DisplayMode mode = Display.getDesktopDisplayMode();
|
|
return new LwjglDisplayMode(mode.getWidth(), mode.getHeight(), mode.getFrequency(), mode.getBitsPerPixel(), mode);
|
|
}
|
|
|
|
@Override
|
|
public void setTitle (String title) {
|
|
Display.setTitle(title);
|
|
}
|
|
|
|
/**
|
|
* Display must be reconfigured via {@link #setWindowedMode(int, int)} for the changes to take
|
|
* effect.
|
|
*/
|
|
@Override
|
|
public void setUndecorated (boolean undecorated) {
|
|
System.setProperty("org.lwjgl.opengl.Window.undecorated", undecorated ? "true" : "false");
|
|
}
|
|
|
|
/**
|
|
* Display must be reconfigured via {@link #setWindowedMode(int, int)} for the changes to take
|
|
* effect.
|
|
*/
|
|
@Override
|
|
public void setResizable (boolean resizable) {
|
|
this.config.resizable = resizable;
|
|
Display.setResizable(resizable);
|
|
}
|
|
|
|
@Override
|
|
public BufferFormat getBufferFormat () {
|
|
return bufferFormat;
|
|
}
|
|
|
|
@Override
|
|
public void setVSync (boolean vsync) {
|
|
this.vsync = vsync;
|
|
Display.setVSyncEnabled(vsync);
|
|
}
|
|
|
|
@Override
|
|
public boolean supportsExtension (String extension) {
|
|
return extensions.contains(extension, false);
|
|
}
|
|
|
|
@Override
|
|
public void setContinuousRendering (boolean isContinuous) {
|
|
this.isContinuous = isContinuous;
|
|
}
|
|
|
|
@Override
|
|
public boolean isContinuousRendering () {
|
|
return isContinuous;
|
|
}
|
|
|
|
@Override
|
|
public void requestRendering () {
|
|
synchronized (this) {
|
|
requestRendering = true;
|
|
}
|
|
}
|
|
|
|
public boolean shouldRender () {
|
|
synchronized (this) {
|
|
boolean rq = requestRendering;
|
|
requestRendering = false;
|
|
return rq || isContinuous || Display.isDirty();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean isFullscreen () {
|
|
return Display.isFullscreen();
|
|
}
|
|
|
|
public boolean isSoftwareMode () {
|
|
return softwareMode;
|
|
}
|
|
|
|
/** A callback used by LwjglApplication when trying to create the display */
|
|
public interface SetDisplayModeCallback {
|
|
/** If the display creation fails, this method will be called. Suggested usage is to modify the passed configuration to use a
|
|
* common width and height, and set fullscreen to false.
|
|
* @return the configuration to be used for a second attempt at creating a display. A null value results in NOT attempting
|
|
* to create the display a second time */
|
|
public LwjglApplicationConfiguration onFailure (LwjglApplicationConfiguration initialConfig);
|
|
}
|
|
|
|
@Override
|
|
public com.badlogic.gdx.graphics.Cursor newCursor (Pixmap pixmap, int xHotspot, int yHotspot) {
|
|
return new LwjglCursor(pixmap, xHotspot, yHotspot);
|
|
}
|
|
|
|
@Override
|
|
public void setCursor (com.badlogic.gdx.graphics.Cursor cursor) {
|
|
if (canvas != null && SharedLibraryLoader.isMac) {
|
|
return;
|
|
}
|
|
try {
|
|
Mouse.setNativeCursor(((LwjglCursor)cursor).lwjglCursor);
|
|
} catch (LWJGLException e) {
|
|
throw new GdxRuntimeException("Could not set cursor image.", e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setSystemCursor (SystemCursor systemCursor) {
|
|
if (canvas != null && SharedLibraryLoader.isMac) {
|
|
return;
|
|
}
|
|
try {
|
|
Mouse.setNativeCursor(null);
|
|
} catch (LWJGLException e) {
|
|
throw new GdxRuntimeException("Couldn't set system cursor");
|
|
}
|
|
}
|
|
|
|
private class LwjglDisplayMode extends DisplayMode {
|
|
org.lwjgl.opengl.DisplayMode mode;
|
|
|
|
public LwjglDisplayMode (int width, int height, int refreshRate, int bitsPerPixel, org.lwjgl.opengl.DisplayMode mode) {
|
|
super(width, height, refreshRate, bitsPerPixel);
|
|
this.mode = mode;
|
|
}
|
|
}
|
|
|
|
private class LwjglMonitor extends Monitor {
|
|
protected LwjglMonitor (int virtualX, int virtualY, String name) {
|
|
super(virtualX, virtualY, name);
|
|
}
|
|
}
|
|
}
|