+/*******************************************************************************\r
+ * Copyright 2011 See AUTHORS file.\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ ******************************************************************************/
package com.badlogic.gdx.backends.jglfw;
import static com.badlogic.jglfw.Glfw.*;
+import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
+import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GL11;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GLCommon;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
+import com.badlogic.jglfw.GlfwVideoMode;
import com.badlogic.jglfw.gl.GL;
-import java.awt.GraphicsDevice;
-import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
/** An implementation of the {@link Graphics} interface based on GLFW.
public class JglfwGraphics implements Graphics {
static int glMajorVersion, glMinorVersion;
- JglfwApplicationConfiguration config;
long window;
- boolean fullscreen;
- int fullscreenMonitorIndex;
- final BufferFormat bufferFormat;
- volatile boolean isContinuous = true;
-
- float deltaTime;
- long frameStart, lastTime;
- int frames, fps;
-
- GLCommon gl;
- JglfwGL10 gl10;
- JglfwGL11 gl11;
- JglfwGL20 gl20;
-
- boolean sync;
- boolean resize;
- volatile boolean requestRendering;
+ private boolean fullscreen;
+ private long fullscreenMonitor;
+ private String title;
+ private boolean resizable, undecorated;
+ private BufferFormat bufferFormat;
+ private boolean vSync;
+ private int x, y, width, height;
+ private boolean visible;
+ private Color initialBackgroundColor;
+ private volatile boolean isContinuous = true, renderRequested;
+ volatile boolean foreground, minimized;
+
+ private float deltaTime;
+ private long frameStart, lastTime = -1;
+ private int frames, fps;
+
+ private GLCommon gl;
+ private JglfwGL10 gl10;
+ private JglfwGL11 gl11;
+ private JglfwGL20 gl20;
public JglfwGraphics (JglfwApplicationConfiguration config) {
- this.config = config;
-
+ // Store values from config.
bufferFormat = new BufferFormat(config.r, config.g, config.b, config.a, config.depth, config.stencil, config.samples, false);
-
- createWindow();
- createGL();
- }
-
- private void createWindow () {
- glfwWindowHint(GLFW_RESIZABLE, config.resizable ? 1 : 0);
- glfwWindowHint(GLFW_RED_BITS, config.r);
- glfwWindowHint(GLFW_GREEN_BITS, config.g);
- glfwWindowHint(GLFW_BLUE_BITS, config.b);
- glfwWindowHint(GLFW_ALPHA_BITS, config.a);
- glfwWindowHint(GLFW_DEPTH_BITS, config.depth);
- glfwWindowHint(GLFW_STENCIL_BITS, config.stencil);
- glfwWindowHint(GLFW_SAMPLES, config.samples);
- glfwWindowHint(GLFW_DEPTH_BITS, config.bitsPerPixel);
-
- long fullscreenMonitor = glfwGetPrimaryMonitor();
- long[] monitors = glfwGetMonitors();
- // Find index of primary monitor.
- for (int i = 0, n = monitors.length; i < n; i++) {
- if (monitors[i] == fullscreenMonitor) {
- fullscreenMonitorIndex = i;
- break;
- }
- }
- // Find monitor specified in config.
- if (config.fullscreen) {
- if (monitors.length > 0) {
- if (config.fullscreenMonitorIndex < monitors.length) fullscreenMonitorIndex = config.fullscreenMonitorIndex;
- fullscreenMonitor = monitors[fullscreenMonitorIndex];
- }
+ title = config.title;
+ resizable = config.resizable;
+ undecorated = config.undecorated;
+ x = config.x;
+ y = config.y;
+ vSync = config.vSync;
+ initialBackgroundColor = config.initialBackgroundColor;
+ if (config.fullscreenMonitorIndex != -1) { // Use monitor specified in config if it is valid.
+ long[] monitors = glfwGetMonitors();
+ if (config.fullscreenMonitorIndex < monitors.length) fullscreenMonitor = monitors[config.fullscreenMonitorIndex];
}
// Create window.
- if (!setDisplayMode(config.width, config.height, config.fullscreen)) {
+ if (!createWindow(config.width, config.height, config.fullscreen)) {
throw new GdxRuntimeException("Unable to create window: " + config.width + "x" + config.height + ", fullscreen: "
+ config.fullscreen);
}
- setVSync(config.vSync);
- if (config.x != -1 && config.y != -1) glfwSetWindowPos(window, config.x, config.y);
- }
-
- private void createGL () {
+ // Create GL.
String version = GL.glGetString(GL11.GL_VERSION);
glMajorVersion = Integer.parseInt("" + version.charAt(0));
glMinorVersion = Integer.parseInt("" + version.charAt(2));
-
if (config.useGL20 && (glMajorVersion >= 2 || version.contains("2.1"))) { // special case for MESA, wtf...
- // FIXME - Add check whether gl 2.0 is actually supported.
gl20 = new JglfwGL20();
gl = gl20;
} else {
gl20 = null;
- if (glMajorVersion == 1 && glMinorVersion < 5) {
+ if (glMajorVersion == 1 && glMinorVersion < 5)
gl10 = new JglfwGL10();
- } else {
+ else {
gl11 = new JglfwGL11();
gl10 = gl11;
}
gl = gl10;
}
-
Gdx.gl = gl;
Gdx.gl10 = gl10;
Gdx.gl11 = gl11;
Gdx.gl20 = gl20;
+
+ if (!config.hidden) show();
+ }
+
+ private boolean createWindow (int width, int height, boolean fullscreen) {
+ if (fullscreen && fullscreenMonitor == 0) fullscreenMonitor = getWindowMonitor();
+
+ glfwWindowHint(GLFW_VISIBLE, 0);
+ glfwWindowHint(GLFW_RESIZABLE, resizable ? 1 : 0);
+ glfwWindowHint(GLFW_UNDECORATED, undecorated ? 1 : 0);
+ glfwWindowHint(GLFW_RED_BITS, bufferFormat.r);
+ glfwWindowHint(GLFW_GREEN_BITS, bufferFormat.g);
+ glfwWindowHint(GLFW_BLUE_BITS, bufferFormat.b);
+ glfwWindowHint(GLFW_ALPHA_BITS, bufferFormat.a);
+ glfwWindowHint(GLFW_DEPTH_BITS, bufferFormat.depth);
+ glfwWindowHint(GLFW_STENCIL_BITS, bufferFormat.stencil);
+ glfwWindowHint(GLFW_SAMPLES, bufferFormat.samples);
+
+ boolean mouseCaptured = window != 0 && glfwGetInputMode(window, GLFW_CURSOR_MODE) == GLFW_CURSOR_CAPTURED;
+
+ long oldWindow = window;
+ long newWindow = glfwCreateWindow(width, height, title, fullscreen ? fullscreenMonitor : 0, oldWindow);
+ if (newWindow == 0) return false;
+ if (oldWindow != 0) glfwDestroyWindow(oldWindow);
+ window = newWindow;
+ this.width = Math.max(1, width);
+ this.height = Math.max(1, height);
+
+ this.fullscreen = fullscreen;
+ if (!fullscreen) {
+ if (x == -1 || y == -1) {
+ DisplayMode mode = getDesktopDisplayMode();
+ x = (mode.width - width) / 2;
+ y = (mode.height - height) / 2;
+ }
+ glfwSetWindowPos(window, x, y);
+ }
+
+ if (!mouseCaptured) glfwSetInputMode(window, GLFW_CURSOR_MODE, GLFW_CURSOR_NORMAL); // Prevent fullscreen from taking mouse.
+
+ glfwMakeContextCurrent(newWindow);
+ setVSync(vSync);
+ if (visible) glfwShowWindow(window);
+
+ return true;
+ }
+
+ void frameStart (long time) {
+ if (lastTime == -1) lastTime = time;
+ deltaTime = (time - lastTime) / 1000000000.0f;
+ lastTime = time;
+
+ if (time - frameStart >= 1000000000) {
+ fps = frames;
+ frames = 0;
+ frameStart = time;
+ }
+ frames++;
+ }
+
+ void sizeChanged (int width, int height) {
+ glfwShowWindow(window); // This is required to refresh the NSOpenGLContext on OSX!
+ width = Math.max(1, width);
+ height = Math.max(1, height);
+ this.width = width;
+ this.height = height;
+ Gdx.gl.glViewport(0, 0, width, height);
+ ApplicationListener listener = Gdx.app.getApplicationListener();
+ if (listener != null) listener.resize(width, height);
+ requestRendering();
+ }
+
+ void positionChanged (int x, int y) {
+ this.x = x;
+ this.y = y;
}
public boolean isGL11Available () {
}
public int getWidth () {
- return glfwGetWindowWidth(window);
+ return width;
}
public int getHeight () {
- return glfwGetWindowHeight(window);
- }
-
- void updateTime () {
- long time = System.nanoTime();
- deltaTime = (time - lastTime) / 1000000000.0f;
- lastTime = time;
-
- if (time - frameStart >= 1000000000) {
- fps = frames;
- frames = 0;
- frameStart = time;
- }
- frames++;
+ return height;
}
public float getDeltaTime () {
}
public float getPpiX () {
+ // return getWidth() / (glfwGetMonitorPhysicalWidth(getWindowMonitor()) * 0.03937f); // mm to inches
return Toolkit.getDefaultToolkit().getScreenResolution();
}
public float getPpiY () {
+ // return getHeight() / (glfwGetMonitorPhysicalHeight(getWindowMonitor()) * 0.03937f); // mm to inches
return Toolkit.getDefaultToolkit().getScreenResolution();
}
public float getPpcX () {
+ // return getWidth() / (glfwGetMonitorPhysicalWidth(getWindowMonitor()) / 10); // mm to cm
return Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f;
}
public float getPpcY () {
+ // return getHeight() / (glfwGetMonitorPhysicalHeight(getWindowMonitor()) / 10); // mm to cm
return Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f;
}
public float getDensity () {
+ // long monitor = getWindowMonitor();
+ // float mmWidth = glfwGetMonitorPhysicalWidth(monitor);
+ // float mmHeight = glfwGetMonitorPhysicalHeight(monitor);
+ // float inches = (float)Math.sqrt(mmWidth * mmWidth + mmHeight * mmHeight) * 0.03937f; // mm to inches
+ // float pixelWidth = getWidth();
+ // float pixelHeight = getHeight();
+ // float pixels = (float)Math.sqrt(pixelWidth * pixelWidth + pixelHeight * pixelHeight);
+ // float diagonalPpi = pixels / inches;
+ // return diagonalPpi / 160f;
return Toolkit.getDefaultToolkit().getScreenResolution() / 160f;
}
return true;
}
+ private long getWindowMonitor () {
+ if (window != 0) {
+ long monitor = glfwGetWindowMonitor(window);
+ if (monitor != 0) return monitor;
+ }
+ return glfwGetPrimaryMonitor();
+ }
+
public DisplayMode[] getDisplayModes () {
- GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
- java.awt.DisplayMode desktopMode = device.getDisplayMode();
- java.awt.DisplayMode[] displayModes = device.getDisplayModes();
Array<DisplayMode> modes = new Array();
- outer:
- for (java.awt.DisplayMode mode : displayModes) {
- for (DisplayMode other : modes)
- if (other.width == mode.getWidth() && other.height == mode.getHeight() && other.bitsPerPixel == mode.getBitDepth())
- continue outer; // Duplicate.
- if (mode.getBitDepth() != desktopMode.getBitDepth()) continue;
- modes.add(new JglfwDisplayMode(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getBitDepth()));
- }
- return modes.toArray();
+ for (GlfwVideoMode mode : glfwGetVideoModes(getWindowMonitor()))
+ modes.add(new JglfwDisplayMode(mode.width, mode.height, 0, mode.redBits + mode.greenBits + mode.blueBits));
+ return modes.toArray(DisplayMode.class);
}
public DisplayMode getDesktopDisplayMode () {
- java.awt.DisplayMode mode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
- return new JglfwDisplayMode(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getBitDepth());
+ GlfwVideoMode mode = glfwGetVideoMode(getWindowMonitor());
+ return new JglfwDisplayMode(mode.width, mode.height, 0, mode.redBits + mode.greenBits + mode.blueBits);
}
public boolean setDisplayMode (DisplayMode displayMode) {
- if (displayMode.bitsPerPixel != 0) glfwWindowHint(GLFW_DEPTH_BITS, displayMode.bitsPerPixel);
- glfwSetWindowSize(window, displayMode.width, displayMode.height);
- return true;
+ bufferFormat = new BufferFormat( //
+ displayMode.bitsPerPixel == 16 ? 5 : 8, //
+ displayMode.bitsPerPixel == 16 ? 6 : 8, //
+ displayMode.bitsPerPixel == 16 ? 6 : 8, //
+ bufferFormat.a, bufferFormat.depth, bufferFormat.stencil, bufferFormat.samples, false);
+ boolean success = createWindow(displayMode.width, displayMode.height, fullscreen);
+ if (success && fullscreen) sizeChanged(displayMode.width, displayMode.height);
+ return success;
}
public boolean setDisplayMode (int width, int height, boolean fullscreen) {
- if (window == 0 || fullscreen != config.fullscreen) {
- long fullscreenMonitor = 0;
- long[] monitors = glfwGetMonitors();
- if (monitors.length > 0)
- fullscreenMonitor = fullscreenMonitorIndex < monitors.length ? monitors[fullscreenMonitorIndex] : 0;
-
- long window = glfwCreateWindow(config.width, config.height, config.title, fullscreenMonitor, 0);
- if (window == 0) return false;
- if (this.window != 0) glfwDestroyWindow(window);
- glfwMakeContextCurrent(window);
- this.window = window;
- return true;
+ if (fullscreen || this.fullscreen) {
+ boolean success = createWindow(width, height, fullscreen);
+ if (success && fullscreen) sizeChanged(width, height);
+ return success;
}
+
glfwSetWindowSize(window, width, height);
return true;
}
public void setTitle (String title) {
+ if (title == null) title = "";
glfwSetWindowTitle(window, title);
+ this.title = title;
}
public void setVSync (boolean vsync) {
- this.sync = vsync;
- if (!config.cpuSync) glfwSwapInterval(vsync ? 1 : 0);
+ this.vSync = vsync;
+ glfwSwapInterval(vsync ? 1 : 0);
}
public BufferFormat getBufferFormat () {
}
public void requestRendering () {
- synchronized (this) {
- requestRendering = true;
- }
+ renderRequested = true;
}
public boolean isFullscreen () {
- return config.fullscreen;
+ return fullscreen;
}
/** Returns the JGLFW window handle. Note this should not be stored externally as it may change if the window is recreated to
return window;
}
+ public int getX () {
+ return x;
+ }
+
+ public int getY () {
+ return y;
+ }
+
+ public void setPosition (int x, int y) {
+ glfwSetWindowPos(window, x, y);
+ }
+
+ public void hide () {
+ visible = false;
+ glfwHideWindow(window);
+ }
+
+ public void show () {
+ visible = true;
+ glfwShowWindow(window);
+
+ Gdx.gl.glClearColor(initialBackgroundColor.r, initialBackgroundColor.g, initialBackgroundColor.b, initialBackgroundColor.a);
+ Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
+ glfwSwapBuffers(window);
+ }
+
+ public boolean isHidden () {
+ return !visible;
+ }
+
+ public boolean isMinimized () {
+ return minimized;
+ }
+
+ public boolean isForeground () {
+ return foreground;
+ }
+
+ public void minimize () {
+ glfwIconifyWindow(window);
+ }
+
+ public void restore () {
+ glfwRestoreWindow(window);
+ }
+
boolean shouldRender () {
- synchronized (this) {
- boolean requestRendering = this.requestRendering;
- this.requestRendering = false;
- return requestRendering || isContinuous;
+ try {
+ return renderRequested || isContinuous;
+ } finally {
+ renderRequested = false;
}
}
super(width, height, refreshRate, bitsPerPixel);
}
}
-}
+}
\ No newline at end of file