2 package com.badlogic.gdx.backends.jglfw;
4 import static com.badlogic.jglfw.Glfw.*;
6 import com.badlogic.gdx.Gdx;
7 import com.badlogic.gdx.Graphics;
8 import com.badlogic.gdx.graphics.GL10;
9 import com.badlogic.gdx.graphics.GL11;
10 import com.badlogic.gdx.graphics.GL20;
11 import com.badlogic.gdx.graphics.GLCommon;
12 import com.badlogic.gdx.utils.Array;
13 import com.badlogic.gdx.utils.GdxRuntimeException;
14 import com.badlogic.jglfw.gl.GL;
16 import java.awt.GraphicsDevice;
17 import java.awt.GraphicsEnvironment;
18 import java.awt.Toolkit;
20 /** An implementation of the {@link Graphics} interface based on GLFW.
21 * @author Nathan Sweet */
22 public class JglfwGraphics implements Graphics {
23 static int glMajorVersion, glMinorVersion;
25 JglfwApplicationConfiguration config;
28 int fullscreenMonitorIndex;
29 final BufferFormat bufferFormat;
30 volatile boolean isContinuous = true;
33 long frameStart, lastTime;
43 volatile boolean requestRendering;
45 public JglfwGraphics (JglfwApplicationConfiguration config) {
48 bufferFormat = new BufferFormat(config.r, config.g, config.b, config.a, config.depth, config.stencil, config.samples, false);
54 private void createWindow () {
55 long fullscreenMonitor = glfwGetPrimaryMonitor();
56 long[] monitors = glfwGetMonitors();
57 // Find index of primary monitor.
58 for (int i = 0, n = monitors.length; i < n; i++) {
59 if (monitors[i] == fullscreenMonitor) {
60 fullscreenMonitorIndex = i;
64 // Find monitor specified in config.
65 if (config.fullscreen) {
66 if (monitors.length > 0) {
67 if (config.fullscreenMonitorIndex < monitors.length) fullscreenMonitorIndex = config.fullscreenMonitorIndex;
68 fullscreenMonitor = monitors[fullscreenMonitorIndex];
73 if (!setDisplayMode(config.width, config.height, config.fullscreen)) {
74 throw new GdxRuntimeException("Unable to create window: " + config.width + "x" + config.height + ", fullscreen: "
78 setVSync(config.vSync);
79 if (config.x != -1 && config.y != -1) glfwSetWindowPos(window, config.x, config.y);
82 private void createGL () {
83 String version = GL.glGetString(GL11.GL_VERSION);
84 glMajorVersion = Integer.parseInt("" + version.charAt(0));
85 glMinorVersion = Integer.parseInt("" + version.charAt(2));
87 if (config.useGL20 && (glMajorVersion >= 2 || version.contains("2.1"))) { // special case for MESA, wtf...
88 // FIXME - Add check for whether GL 2.0 is actually supported.
89 gl20 = new JglfwGL20();
93 if (glMajorVersion == 1 && glMinorVersion < 5) {
94 gl10 = new JglfwGL10();
96 gl11 = new JglfwGL11();
108 public boolean isGL11Available () {
112 public boolean isGL20Available () {
116 public GLCommon getGLCommon () {
120 public GL10 getGL10 () {
124 public GL11 getGL11 () {
128 public GL20 getGL20 () {
132 public int getWidth () {
133 return glfwGetWindowWidth(window);
136 public int getHeight () {
137 return glfwGetWindowHeight(window);
141 long time = System.nanoTime();
142 deltaTime = (time - lastTime) / 1000000000.0f;
145 if (time - frameStart >= 1000000000) {
153 public float getDeltaTime () {
157 public float getRawDeltaTime () {
161 public int getFramesPerSecond () {
165 public GraphicsType getType () {
166 return GraphicsType.JGLFW;
169 public float getPpiX () {
170 return Toolkit.getDefaultToolkit().getScreenResolution();
173 public float getPpiY () {
174 return Toolkit.getDefaultToolkit().getScreenResolution();
177 public float getPpcX () {
178 return Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f;
181 public float getPpcY () {
182 return Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f;
185 public float getDensity () {
186 return Toolkit.getDefaultToolkit().getScreenResolution() / 160f;
189 public boolean supportsDisplayModeChange () {
193 public DisplayMode[] getDisplayModes () {
194 GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
195 java.awt.DisplayMode desktopMode = device.getDisplayMode();
196 java.awt.DisplayMode[] displayModes = device.getDisplayModes();
197 Array<DisplayMode> modes = new Array();
199 for (java.awt.DisplayMode mode : displayModes) {
200 for (DisplayMode other : modes)
201 if (other.width == mode.getWidth() && other.height == mode.getHeight() && other.bitsPerPixel == mode.getBitDepth())
202 continue outer; // Duplicate.
203 if (mode.getBitDepth() != desktopMode.getBitDepth()) continue;
204 modes.add(new JglfwDisplayMode(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getBitDepth()));
206 return modes.toArray(DisplayMode.class);
209 public DisplayMode getDesktopDisplayMode () {
210 java.awt.DisplayMode mode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
211 return new JglfwDisplayMode(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getBitDepth());
214 public boolean setDisplayMode (DisplayMode displayMode) {
215 if (displayMode.bitsPerPixel != 0) glfwWindowHint(GLFW_DEPTH_BITS, displayMode.bitsPerPixel);
216 glfwSetWindowSize(window, displayMode.width, displayMode.height);
220 public boolean setDisplayMode (int width, int height, boolean fullscreen) {
221 if (window == 0 || fullscreen != config.fullscreen) {
222 long fullscreenMonitor = 0;
223 long[] monitors = glfwGetMonitors();
224 if (monitors.length > 0)
225 fullscreenMonitor = fullscreenMonitorIndex < monitors.length ? monitors[fullscreenMonitorIndex] : 0;
227 // need to set the window hints every time we create a window, glfwCreateWindow resets them.
228 glfwWindowHint(GLFW_RESIZABLE, config.resizable ? 1 : 0);
229 glfwWindowHint(GLFW_RED_BITS, config.r);
230 glfwWindowHint(GLFW_GREEN_BITS, config.g);
231 glfwWindowHint(GLFW_BLUE_BITS, config.b);
232 glfwWindowHint(GLFW_ALPHA_BITS, config.a);
233 glfwWindowHint(GLFW_DEPTH_BITS, config.depth);
234 glfwWindowHint(GLFW_STENCIL_BITS, config.stencil);
235 glfwWindowHint(GLFW_SAMPLES, config.samples);
236 glfwWindowHint(GLFW_DEPTH_BITS, config.bitsPerPixel);
238 // share old window if any, so context service
239 long window = glfwCreateWindow(config.width, config.height, config.title, 0, this.window);
240 if (window == 0) return false;
241 if (this.window != 0) glfwDestroyWindow(window);
242 glfwMakeContextCurrent(window);
243 this.window = window;
246 glfwSetWindowSize(window, width, height);
250 public void setTitle (String title) {
251 glfwSetWindowTitle(window, title);
254 public void setVSync (boolean vsync) {
256 glfwSwapInterval(vsync ? 1 : 0);
259 public BufferFormat getBufferFormat () {
263 public boolean supportsExtension (String extension) {
264 return glfwExtensionSupported(extension);
267 public void setContinuousRendering (boolean isContinuous) {
268 this.isContinuous = isContinuous;
271 public boolean isContinuousRendering () {
275 public void requestRendering () {
276 synchronized (this) {
277 requestRendering = true;
281 public boolean isFullscreen () {
282 return config.fullscreen;
285 /** Returns the JGLFW window handle. Note this should not be stored externally as it may change if the window is recreated to
286 * enter/exit fullscreen. */
287 public long getWindow () {
291 boolean shouldRender () {
292 synchronized (this) {
293 boolean requestRendering = this.requestRendering;
294 this.requestRendering = false;
295 return requestRendering || isContinuous;
299 static class JglfwDisplayMode extends DisplayMode {
300 protected JglfwDisplayMode (int width, int height, int refreshRate, int bitsPerPixel) {
301 super(width, height, refreshRate, bitsPerPixel);