OSDN Git Service

Merge pull request #309 from xoppa/math
[mikumikustudio/libgdx-mikumikustudio.git] / backends / gdx-backend-jglfw / src / com / badlogic / gdx / backends / jglfw / JglfwGraphics.java
1
2 package com.badlogic.gdx.backends.jglfw;
3
4 import static com.badlogic.jglfw.Glfw.*;
5
6 import com.badlogic.gdx.ApplicationListener;
7 import com.badlogic.gdx.Gdx;
8 import com.badlogic.gdx.Graphics;
9 import com.badlogic.gdx.graphics.Color;
10 import com.badlogic.gdx.graphics.GL10;
11 import com.badlogic.gdx.graphics.GL11;
12 import com.badlogic.gdx.graphics.GL20;
13 import com.badlogic.gdx.graphics.GLCommon;
14 import com.badlogic.gdx.utils.Array;
15 import com.badlogic.gdx.utils.GdxRuntimeException;
16 import com.badlogic.jglfw.GlfwVideoMode;
17 import com.badlogic.jglfw.gl.GL;
18
19 import java.awt.Toolkit;
20
21 /** An implementation of the {@link Graphics} interface based on GLFW.
22  * @author Nathan Sweet */
23 public class JglfwGraphics implements Graphics {
24         static int glMajorVersion, glMinorVersion;
25
26         long window;
27         private boolean fullscreen;
28         private long fullscreenMonitor;
29         private String title;
30         private boolean resizable, undecorated;
31         private BufferFormat bufferFormat;
32         private boolean vSync;
33         private int x, y, width, height;
34         private boolean visible;
35         private Color initialBackgroundColor;
36         private volatile boolean isContinuous = true, renderRequested;
37         volatile boolean foreground, minimized;
38
39         private float deltaTime;
40         private long frameStart, lastTime = -1;
41         private int frames, fps;
42
43         private GLCommon gl;
44         private JglfwGL10 gl10;
45         private JglfwGL11 gl11;
46         private JglfwGL20 gl20;
47
48         public JglfwGraphics (JglfwApplicationConfiguration config) {
49                 // Store values from config.
50                 bufferFormat = new BufferFormat(config.r, config.g, config.b, config.a, config.depth, config.stencil, config.samples, false);
51                 title = config.title;
52                 resizable = config.resizable;
53                 undecorated = config.undecorated;
54                 x = config.x;
55                 y = config.y;
56                 vSync = config.vSync;
57                 initialBackgroundColor = config.initialBackgroundColor;
58                 if (config.fullscreenMonitorIndex != -1) { // Use monitor specified in config if it is valid.
59                         long[] monitors = glfwGetMonitors();
60                         if (config.fullscreenMonitorIndex < monitors.length) fullscreenMonitor = monitors[config.fullscreenMonitorIndex];
61                 }
62
63                 // Create window.
64                 if (!createWindow(config.width, config.height, config.fullscreen)) {
65                         throw new GdxRuntimeException("Unable to create window: " + config.width + "x" + config.height + ", fullscreen: "
66                                 + config.fullscreen);
67                 }
68
69                 // Create GL.
70                 String version = GL.glGetString(GL11.GL_VERSION);
71                 glMajorVersion = Integer.parseInt("" + version.charAt(0));
72                 glMinorVersion = Integer.parseInt("" + version.charAt(2));
73                 if (config.useGL20 && (glMajorVersion >= 2 || version.contains("2.1"))) { // special case for MESA, wtf...
74                         gl20 = new JglfwGL20();
75                         gl = gl20;
76                 } else {
77                         gl20 = null;
78                         if (glMajorVersion == 1 && glMinorVersion < 5)
79                                 gl10 = new JglfwGL10();
80                         else {
81                                 gl11 = new JglfwGL11();
82                                 gl10 = gl11;
83                         }
84                         gl = gl10;
85                 }
86                 Gdx.gl = gl;
87                 Gdx.gl10 = gl10;
88                 Gdx.gl11 = gl11;
89                 Gdx.gl20 = gl20;
90
91                 if (!config.hidden) show();
92         }
93
94         private boolean createWindow (int width, int height, boolean fullscreen) {
95                 if (fullscreen && fullscreenMonitor == 0) fullscreenMonitor = getWindowMonitor();
96
97                 glfwWindowHint(GLFW_VISIBLE, 0);
98                 glfwWindowHint(GLFW_RESIZABLE, resizable ? 1 : 0);
99                 glfwWindowHint(GLFW_UNDECORATED, undecorated ? 1 : 0);
100                 glfwWindowHint(GLFW_RED_BITS, bufferFormat.r);
101                 glfwWindowHint(GLFW_GREEN_BITS, bufferFormat.g);
102                 glfwWindowHint(GLFW_BLUE_BITS, bufferFormat.b);
103                 glfwWindowHint(GLFW_ALPHA_BITS, bufferFormat.a);
104                 glfwWindowHint(GLFW_DEPTH_BITS, bufferFormat.depth);
105                 glfwWindowHint(GLFW_STENCIL_BITS, bufferFormat.stencil);
106                 glfwWindowHint(GLFW_SAMPLES, bufferFormat.samples);
107
108                 boolean mouseCaptured = window != 0 && glfwGetInputMode(window, GLFW_CURSOR_MODE) == GLFW_CURSOR_CAPTURED;
109
110                 long oldWindow = window;
111                 long newWindow = glfwCreateWindow(width, height, title, fullscreen ? fullscreenMonitor : 0, oldWindow);
112                 if (newWindow == 0) return false;
113                 if (oldWindow != 0) glfwDestroyWindow(oldWindow);
114                 window = newWindow;
115                 this.width = Math.max(1, width);
116                 this.height = Math.max(1, height);
117
118                 this.fullscreen = fullscreen;
119                 if (!fullscreen) {
120                         if (x == -1 || y == -1) {
121                                 DisplayMode mode = getDesktopDisplayMode();
122                                 x = (mode.width - width) / 2;
123                                 y = (mode.height - height) / 2;
124                         }
125                         glfwSetWindowPos(window, x, y);
126                 }
127
128                 if (!mouseCaptured) glfwSetInputMode(window, GLFW_CURSOR_MODE, GLFW_CURSOR_NORMAL); // Prevent fullscreen from taking mouse.
129
130                 glfwMakeContextCurrent(newWindow);
131                 setVSync(vSync);
132                 if (visible) glfwShowWindow(window);
133
134                 return true;
135         }
136
137         void frameStart (long time) {
138                 if (lastTime == -1) lastTime = time;
139                 deltaTime = (time - lastTime) / 1000000000.0f;
140                 lastTime = time;
141
142                 if (time - frameStart >= 1000000000) {
143                         fps = frames;
144                         frames = 0;
145                         frameStart = time;
146                 }
147                 frames++;
148         }
149
150         void sizeChanged (int width, int height) {
151                 width = Math.max(1, width);
152                 height = Math.max(1, height);
153                 this.width = width;
154                 this.height = height;
155                 Gdx.gl.glViewport(0, 0, width, height);
156                 ApplicationListener listener = Gdx.app.getApplicationListener();
157                 if (listener != null) listener.resize(width, height);
158                 requestRendering();
159         }
160
161         void positionChanged (int x, int y) {
162                 this.x = x;
163                 this.y = y;
164         }
165
166         public boolean isGL11Available () {
167                 return gl11 != null;
168         }
169
170         public boolean isGL20Available () {
171                 return gl20 != null;
172         }
173
174         public GLCommon getGLCommon () {
175                 return gl;
176         }
177
178         public GL10 getGL10 () {
179                 return gl10;
180         }
181
182         public GL11 getGL11 () {
183                 return gl11;
184         }
185
186         public GL20 getGL20 () {
187                 return gl20;
188         }
189
190         public int getWidth () {
191                 return width;
192         }
193
194         public int getHeight () {
195                 return height;
196         }
197
198         public float getDeltaTime () {
199                 return deltaTime;
200         }
201
202         public float getRawDeltaTime () {
203                 return deltaTime;
204         }
205
206         public int getFramesPerSecond () {
207                 return fps;
208         }
209
210         public GraphicsType getType () {
211                 return GraphicsType.JGLFW;
212         }
213
214         public float getPpiX () {
215                 // return getWidth() / (glfwGetMonitorPhysicalWidth(getWindowMonitor()) * 0.03937f); // mm to inches
216                 return Toolkit.getDefaultToolkit().getScreenResolution();
217         }
218
219         public float getPpiY () {
220                 // return getHeight() / (glfwGetMonitorPhysicalHeight(getWindowMonitor()) * 0.03937f); // mm to inches
221                 return Toolkit.getDefaultToolkit().getScreenResolution();
222         }
223
224         public float getPpcX () {
225                 // return getWidth() / (glfwGetMonitorPhysicalWidth(getWindowMonitor()) / 10); // mm to cm
226                 return Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f;
227         }
228
229         public float getPpcY () {
230                 // return getHeight() / (glfwGetMonitorPhysicalHeight(getWindowMonitor()) / 10); // mm to cm
231                 return Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f;
232         }
233
234         public float getDensity () {
235                 // long monitor = getWindowMonitor();
236                 // float mmWidth = glfwGetMonitorPhysicalWidth(monitor);
237                 // float mmHeight = glfwGetMonitorPhysicalHeight(monitor);
238                 // float inches = (float)Math.sqrt(mmWidth * mmWidth + mmHeight * mmHeight) * 0.03937f; // mm to inches
239                 // float pixelWidth = getWidth();
240                 // float pixelHeight = getHeight();
241                 // float pixels = (float)Math.sqrt(pixelWidth * pixelWidth + pixelHeight * pixelHeight);
242                 // float diagonalPpi = pixels / inches;
243                 // return diagonalPpi / 160f;
244                 return Toolkit.getDefaultToolkit().getScreenResolution() / 160f;
245         }
246
247         public boolean supportsDisplayModeChange () {
248                 return true;
249         }
250
251         private long getWindowMonitor () {
252                 if (window != 0) {
253                         long monitor = glfwGetWindowMonitor(window);
254                         if (monitor != 0) return monitor;
255                 }
256                 return glfwGetPrimaryMonitor();
257         }
258
259         public DisplayMode[] getDisplayModes () {
260                 Array<DisplayMode> modes = new Array();
261                 for (GlfwVideoMode mode : glfwGetVideoModes(getWindowMonitor()))
262                         modes.add(new JglfwDisplayMode(mode.width, mode.height, 0, mode.redBits + mode.greenBits + mode.blueBits));
263                 return modes.toArray(DisplayMode.class);
264         }
265
266         public DisplayMode getDesktopDisplayMode () {
267                 GlfwVideoMode mode = glfwGetVideoMode(getWindowMonitor());
268                 return new JglfwDisplayMode(mode.width, mode.height, 0, mode.redBits + mode.greenBits + mode.blueBits);
269         }
270
271         public boolean setDisplayMode (DisplayMode displayMode) {
272                 bufferFormat = new BufferFormat( //
273                         displayMode.bitsPerPixel == 16 ? 5 : 8, //
274                         displayMode.bitsPerPixel == 16 ? 6 : 8, //
275                         displayMode.bitsPerPixel == 16 ? 6 : 8, //
276                         bufferFormat.a, bufferFormat.depth, bufferFormat.stencil, bufferFormat.samples, false);
277                 boolean success = createWindow(displayMode.width, displayMode.height, fullscreen);
278                 if (success && fullscreen) sizeChanged(displayMode.width, displayMode.height);
279                 return success;
280         }
281
282         public boolean setDisplayMode (int width, int height, boolean fullscreen) {
283                 if (fullscreen || this.fullscreen) {
284                         boolean success = createWindow(width, height, fullscreen);
285                         if (success && fullscreen) sizeChanged(width, height);
286                         return success;
287                 }
288
289                 glfwSetWindowSize(window, width, height);
290                 return true;
291         }
292
293         public void setTitle (String title) {
294                 if (title == null) title = "";
295                 glfwSetWindowTitle(window, title);
296                 this.title = title;
297         }
298
299         public void setVSync (boolean vsync) {
300                 this.vSync = vsync;
301                 glfwSwapInterval(vsync ? 1 : 0);
302         }
303
304         public BufferFormat getBufferFormat () {
305                 return bufferFormat;
306         }
307
308         public boolean supportsExtension (String extension) {
309                 return glfwExtensionSupported(extension);
310         }
311
312         public void setContinuousRendering (boolean isContinuous) {
313                 this.isContinuous = isContinuous;
314         }
315
316         public boolean isContinuousRendering () {
317                 return isContinuous;
318         }
319
320         public void requestRendering () {
321                 renderRequested = true;
322         }
323
324         public boolean isFullscreen () {
325                 return fullscreen;
326         }
327
328         /** Returns the JGLFW window handle. Note this should not be stored externally as it may change if the window is recreated to
329          * enter/exit fullscreen. */
330         public long getWindow () {
331                 return window;
332         }
333
334         public int getX () {
335                 return x;
336         }
337
338         public int getY () {
339                 return y;
340         }
341
342         public void setPosition (int x, int y) {
343                 glfwSetWindowPos(window, x, y);
344         }
345
346         public void hide () {
347                 visible = false;
348                 glfwHideWindow(window);
349         }
350
351         public void show () {
352                 visible = true;
353                 glfwShowWindow(window);
354
355                 Gdx.gl.glClearColor(initialBackgroundColor.r, initialBackgroundColor.g, initialBackgroundColor.b, initialBackgroundColor.a);
356                 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
357                 glfwSwapBuffers(window);
358         }
359
360         public boolean isHidden () {
361                 return !visible;
362         }
363
364         public boolean isMinimized () {
365                 return minimized;
366         }
367
368         public boolean isForeground () {
369                 return foreground;
370         }
371
372         public void minimize () {
373                 glfwIconifyWindow(window);
374         }
375
376         public void restore () {
377                 glfwRestoreWindow(window);
378         }
379
380         boolean shouldRender () {
381                 try {
382                         return renderRequested || isContinuous;
383                 } finally {
384                         renderRequested = false;
385                 }
386         }
387
388         static class JglfwDisplayMode extends DisplayMode {
389                 protected JglfwDisplayMode (int width, int height, int refreshRate, int bitsPerPixel) {
390                         super(width, height, refreshRate, bitsPerPixel);
391                 }
392         }
393 }