Jogamp
Copied JOGL_2_SANDBOX r1957 on to trunk; JOGL_2_SANDBOX branch is now closed
[jogl.git] / src / newt / classes / com / sun / javafx / newt / opengl / GLWindow.java
CommitLineData
a959c53b
KR
1/*
2 * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * - Redistribution of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistribution in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * Neither the name of Sun Microsystems, Inc. or the names of
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * This software is provided "AS IS," without a warranty of any kind. ALL
20 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
23 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
24 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
25 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
26 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
27 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
28 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
29 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
30 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31 *
32 */
33
34package com.sun.javafx.newt.opengl;
35
36import com.sun.javafx.newt.*;
37import javax.media.nativewindow.*;
38import javax.media.opengl.*;
39import com.sun.opengl.impl.GLDrawableHelper;
40
41/**
42 * An implementation of {@link Window} which is customized for OpenGL
43 * use, and which implements the {@link
44 * javax.media.opengl.GLAutoDrawable} interface. For convenience, this
45 * window class guarantees that its OpenGL context is current inside
46 * the various EventListeners' callbacks (MouseListener, KeyListener,
47 * etc.).
48 */
49public class GLWindow extends Window implements GLAutoDrawable {
50 /**
51 * Event handling mode: EVENT_HANDLER_GL_NONE.
52 * No GL context is current, while calling the EventListener.
53 * This might be inconvenient, but don't impact the performance.
54 *
55 * @see com.sun.javafx.newt.GLWindow#setEventHandlerMode(int)
56 */
57 public static final int EVENT_HANDLER_GL_NONE = 0;
58
59 /**
60 * Event handling mode: EVENT_HANDLER_GL_CURRENT.
61 * The GL context is made current, while calling the EventListener.
62 * This might be convenient, but impacts the performance
63 * due to context switches.
64 *
65 * This is the default setting!
66 *
67 * @see com.sun.javafx.newt.GLWindow#setEventHandlerMode(int)
68 */
69 public static final int EVENT_HANDLER_GL_CURRENT = (1 << 0);
70
71 private Window window;
72
73 /** Constructor. Do not call this directly -- use {@link
74 create()} instead. */
75 protected GLWindow(Window window, boolean ownerOfDisplayAndScreen) {
76 this.ownerOfDisplayAndScreen = ownerOfDisplayAndScreen;
77 this.window = window;
78 this.window.setAutoDrawableClient(true);
79 window.addWindowListener(new WindowListener() {
80 public void windowResized(WindowEvent e) {
81 sendReshape = true;
82 }
83
84 public void windowMoved(WindowEvent e) {
85 }
86
87 public void windowGainedFocus(WindowEvent e) {
88 }
89
90 public void windowLostFocus(WindowEvent e) {
91 }
92
93 public void windowDestroyNotify(WindowEvent e) {
94 sendDestroy = true;
95 }
96 });
97 }
98
99 /** Creates a new GLWindow on the local display, screen 0, with a
100 dummy visual ID, and with the default GLCapabilities. */
101 public static GLWindow create() {
102 return create(null, null, false);
103 }
104
105 public static GLWindow create(boolean undecorated) {
106 return create(null, null, undecorated);
107 }
108
109 /** Creates a new GLWindow referring to the given window. */
110 public static GLWindow create(Window window) {
111 return create(window, null, false);
112 }
113 public static GLWindow create(GLCapabilities caps) {
114 return create(null, caps, false);
115 }
116
117 /** Creates a new GLWindow on the local display, screen 0, with a
118 dummy visual ID, and with the given GLCapabilities. */
119 public static GLWindow create(GLCapabilities caps, boolean undecorated) {
120 return create(null, caps, undecorated);
121 }
122
123 /** Creates a new GLWindow referring to the given window, and with the given GLCapabilities. */
124 public static GLWindow create(Window window, GLCapabilities caps) {
125 return create(window, caps, false);
126 }
127
128 public static GLWindow create(Window window,
129 GLCapabilities caps,
130 boolean undecorated) {
131 if (caps == null) {
132 caps = new GLCapabilities(null); // default ..
133 }
134
135 boolean ownerOfDisplayAndScreen=false;
136 if (window == null) {
137 ownerOfDisplayAndScreen = true;
138 Display display = NewtFactory.createDisplay(null); // local display
139 Screen screen = NewtFactory.createScreen(display, 0); // screen 0
140 window = NewtFactory.createWindow(screen, caps, undecorated);
141 }
142
143 return new GLWindow(window, ownerOfDisplayAndScreen);
144 }
145
146 protected void createNative(Capabilities caps) {
147 shouldNotCallThis();
148 }
149
150 protected void closeNative() {
151 shouldNotCallThis();
152 }
153
154 protected void dispose(boolean regenerate) {
155 if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
156 Exception e1 = new Exception("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", 1: "+this);
157 e1.printStackTrace();
158 }
159
160 sendDisposeEvent();
161
162 if (context != null) {
163 context.destroy();
164 }
165 if (drawable != null) {
166 drawable.setRealized(false);
167 }
168
169 if(null!=window) {
170 window.disposeSurfaceHandle();
171 }
172
173 if(regenerate) {
174 if(null==window) {
175 throw new GLException("GLWindow.dispose(true): null window");
176 }
177
178 // recreate GLDrawable, to reflect the new graphics configurations
179 NativeWindow nw;
180 if (window.getWrappedWindow() != null) {
181 nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration());
182 } else {
183 nw = window;
184 }
185 drawable = factory.createGLDrawable(nw);
186 drawable.setRealized(true);
187 if(getSurfaceHandle()==0) {
188 throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this);
189 }
190 context = drawable.createContext(null);
191 sendReshape = true; // ensure a reshape event is send ..
192 }
193
194 if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
195 System.out.println("GLWindow.dispose("+regenerate+") "+Thread.currentThread().getName()+", fin: "+this);
196 }
197 }
198
199 public synchronized void destroy() {
200 if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
201 Exception e1 = new Exception("GLWindow.destroy "+Thread.currentThread().getName()+", 1: "+this);
202 e1.printStackTrace();
203 }
204
205 dispose(false);
206
207 Screen _screen = null;
208 Display _device = null;
209 if(null!=window) {
210 if(ownerOfDisplayAndScreen) {
211 _screen = getScreen();
212 if(null != _screen) {
213 _device = _screen.getDisplay();
214 }
215 }
216 window.destroy();
217 }
218
219 if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) {
220 System.out.println("GLWindow.destroy "+Thread.currentThread().getName()+", fin: "+this);
221 }
222
223 drawable = null;
224 context = null;
225
226 if(null != _screen) {
227 _screen.destroy();
228 }
229 if(null != _device) {
230 _device.destroy();
231 }
232 window = null;
233 }
234
235 public boolean getPerfLogEnabled() { return perfLog; }
236
237 public void enablePerfLog(boolean v) {
238 perfLog = v;
239 }
240
241 /**
242 * Sets the event handling mode.
243 *
244 * @see com.sun.javafx.newt.GLWindow#EVENT_HANDLER_GL_NONE
245 * @see com.sun.javafx.newt.GLWindow#EVENT_HANDLER_GL_CURRENT
246 */
247 public void setEventHandlerMode(int mode) {
248 eventHandlerMode = mode;
249 }
250
251 public int getEventHandlerMode() {
252 return eventHandlerMode;
253 }
254
255 public void pumpMessages(int eventMask) {
256 if( 0 == (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) {
257 window.pumpMessages(eventMask);
258 } else {
259 pumpMessagesWithEventMaskAction.eventMask = eventMask;
260 pumpMessagesImpl(pumpMessagesWithEventMaskAction);
261 }
262 }
263
264 public void pumpMessages() {
265 if( 0 == (eventHandlerMode & EVENT_HANDLER_GL_CURRENT) ) {
266 window.pumpMessages();
267 } else {
268 pumpMessagesImpl(pumpMessagesAction);
269 }
270 }
271
272 class PumpMessagesWithEventMaskAction implements Runnable {
273 private int eventMask;
274
275 public void run() {
276 window.pumpMessages(eventMask);
277 }
278 }
279 private PumpMessagesWithEventMaskAction pumpMessagesWithEventMaskAction = new PumpMessagesWithEventMaskAction();
280
281 class PumpMessagesAction implements Runnable {
282 public void run() {
283 window.pumpMessages();
284 }
285 }
286 private PumpMessagesAction pumpMessagesAction = new PumpMessagesAction();
287
288 private void pumpMessagesImpl(Runnable pumpMessagesAction) {
289 // pumpMessagesAction.run();
290
291 boolean autoSwapBuffer = helper.getAutoSwapBufferMode();
292 helper.setAutoSwapBufferMode(false);
293 try {
294 helper.invokeGL(drawable, context, pumpMessagesAction, initAction);
295 } finally {
296 helper.setAutoSwapBufferMode(autoSwapBuffer);
297 }
298
299 }
300
301 protected void dispatchMessages(int eventMask) {
302 shouldNotCallThis();
303 }
304
305 public void setVisible(boolean visible) {
306 window.setVisible(visible);
307 if (visible && context == null) {
308 NativeWindow nw;
309 if (window.getWrappedWindow() != null) {
310 nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration());
311 } else {
312 nw = window;
313 }
314 GLCapabilities glCaps = (GLCapabilities) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities();
315 factory = GLDrawableFactory.getFactory(glCaps.getGLProfile());
316 drawable = factory.createGLDrawable(nw);
317 drawable.setRealized(true);
318 if(getSurfaceHandle()==0) {
319 throw new GLException("SurfaceHandle==NULL after setRealize(true) "+this);
320 }
321 context = drawable.createContext(null);
322 sendReshape = true; // ensure a reshape event is send ..
323 }
324 }
325
326 public Screen getScreen() {
327 return window.getScreen();
328 }
329
330 public void setTitle(String title) {
331 window.setTitle(title);
332 }
333
334 public String getTitle() {
335 return window.getTitle();
336 }
337
338 public void setUndecorated(boolean value) {
339 window.setUndecorated(value);
340 }
341
342 public boolean isUndecorated() {
343 return window.isUndecorated();
344 }
345
346 public void setSize(int width, int height) {
347 window.setSize(width, height);
348 }
349
350 public void setPosition(int x, int y) {
351 window.setPosition(x, y);
352 }
353
354 public boolean setFullscreen(boolean fullscreen) {
355 return window.setFullscreen(fullscreen);
356 }
357
358 public boolean isVisible() {
359 return window.isVisible();
360 }
361
362 public int getX() {
363 return window.getX();
364 }
365
366 public int getY() {
367 return window.getY();
368 }
369
370 public int getWidth() {
371 return window.getWidth();
372 }
373
374 public int getHeight() {
375 return window.getHeight();
376 }
377
378 public boolean isFullscreen() {
379 return window.isFullscreen();
380 }
381
382 public void addMouseListener(MouseListener l) {
383 window.addMouseListener(l);
384 }
385
386 public void removeMouseListener(MouseListener l) {
387 window.removeMouseListener(l);
388 }
389
390 public MouseListener[] getMouseListeners() {
391 return window.getMouseListeners();
392 }
393
394 public void addKeyListener(KeyListener l) {
395 window.addKeyListener(l);
396 }
397
398 public void removeKeyListener(KeyListener l) {
399 window.removeKeyListener(l);
400 }
401
402 public KeyListener[] getKeyListeners() {
403 return window.getKeyListeners();
404 }
405
406 public void addWindowListener(WindowListener l) {
407 window.addWindowListener(l);
408 }
409
410 public void removeWindowListener(WindowListener l) {
411 window.removeWindowListener(l);
412 }
413
414 public WindowListener[] getWindowListeners() {
415 return window.getWindowListeners();
416 }
417
418 public String toString() {
419 return "NEWT-GLWindow[ "+drawable+", \n\t"+window+", \n\t"+helper+", \n\t"+factory+"]";
420 }
421
422 //----------------------------------------------------------------------
423 // OpenGL-related methods and state
424 //
425
426 private int eventHandlerMode = EVENT_HANDLER_GL_CURRENT;
427 private GLDrawableFactory factory;
428 private GLDrawable drawable;
429 private GLContext context;
430 private GLDrawableHelper helper = new GLDrawableHelper();
431 // To make reshape events be sent immediately before a display event
432 private boolean sendReshape=false;
433 private boolean sendDestroy=false;
434 private boolean perfLog = false;
435
436 public GLDrawableFactory getFactory() {
437 return factory;
438 }
439
440 public void setContext(GLContext newCtx) {
441 context = newCtx;
442 }
443
444 public GLContext getContext() {
445 return context;
446 }
447
448 public GL getGL() {
449 if (context == null) {
450 return null;
451 }
452 return context.getGL();
453 }
454
455 public void setGL(GL gl) {
456 if (context != null) {
457 context.setGL(gl);
458 }
459 }
460
461 public void addGLEventListener(GLEventListener listener) {
462 helper.addGLEventListener(listener);
463 }
464
465 public void removeGLEventListener(GLEventListener listener) {
466 helper.removeGLEventListener(listener);
467 }
468
469 public void display() {
470 if(getSurfaceHandle()!=0) {
471 pumpMessages();
472 if(window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) {
473 dispose(true);
474 }
475 if (sendDestroy) {
476 destroy();
477 sendDestroy=false;
478 } else {
479 helper.invokeGL(drawable, context, displayAction, initAction);
480 }
481 }
482 }
483
484 private void sendDisposeEvent() {
485 if(disposeAction!=null && drawable!=null && context != null && window!=null && getSurfaceHandle()!=0) {
486 helper.invokeGL(drawable, context, disposeAction, null);
487 }
488 }
489
490 public void setAutoSwapBufferMode(boolean onOrOff) {
491 helper.setAutoSwapBufferMode(onOrOff);
492 }
493
494 public boolean getAutoSwapBufferMode() {
495 return helper.getAutoSwapBufferMode();
496 }
497
498 public void swapBuffers() {
499 if(getSurfaceHandle()!=0) {
500 if (context != null && context != GLContext.getCurrent()) {
501 // Assume we should try to make the context current before swapping the buffers
502 helper.invokeGL(drawable, context, swapBuffersAction, initAction);
503 } else {
504 drawable.swapBuffers();
505 }
506 }
507 }
508
509 class InitAction implements Runnable {
510 public void run() {
511 helper.init(GLWindow.this);
512 startTime = System.currentTimeMillis();
513 curTime = startTime;
514 if(perfLog) {
515 lastCheck = startTime;
516 totalFrames = 0; lastFrames = 0;
517 }
518 }
519 }
520 private InitAction initAction = new InitAction();
521
522 class DisposeAction implements Runnable {
523 public void run() {
524 helper.dispose(GLWindow.this);
525 }
526 }
527 private DisposeAction disposeAction = new DisposeAction();
528
529 class DisplayAction implements Runnable {
530 public void run() {
531 if (sendReshape) {
532 int width = getWidth();
533 int height = getHeight();
534 getGL().glViewport(0, 0, width, height);
535 helper.reshape(GLWindow.this, 0, 0, width, height);
536 sendReshape = false;
537 }
538
539 helper.display(GLWindow.this);
540
541 curTime = System.currentTimeMillis();
542 totalFrames++;
543
544 if(perfLog) {
545 long dt0, dt1;
546 lastFrames++;
547 dt0 = curTime-lastCheck;
548 if ( dt0 > 5000 ) {
549 dt1 = curTime-startTime;
550 System.out.println(dt0/1000 +"s: "+ lastFrames + "f, " + (lastFrames*1000)/dt0 + " fps, "+dt0/lastFrames+" ms/f; "+
551 "total: "+ dt1/1000+"s, "+(totalFrames*1000)/dt1 + " fps, "+dt1/totalFrames+" ms/f");
552 lastCheck=curTime;
553 lastFrames=0;
554 }
555 }
556 }
557 }
558
559 public long getStartTime() { return startTime; }
560 public long getCurrentTime() { return curTime; }
561 public long getDuration() { return curTime-startTime; }
562 public int getTotalFrames() { return totalFrames; }
563
564 private long startTime = 0;
565 private long curTime = 0;
566 private long lastCheck = 0;
567 private int totalFrames = 0, lastFrames = 0;
568 private boolean ownerOfDisplayAndScreen;
569
570 private DisplayAction displayAction = new DisplayAction();
571
572 class SwapBuffersAction implements Runnable {
573 public void run() {
574 drawable.swapBuffers();
575 }
576 }
577
578 private SwapBuffersAction swapBuffersAction = new SwapBuffersAction();
579
580 //----------------------------------------------------------------------
581 // GLDrawable methods
582 //
583
584 public NativeWindow getNativeWindow() {
585 return null!=drawable ? drawable.getNativeWindow() : null;
586 }
587
588 public synchronized int lockSurface() throws NativeWindowException {
589 if(null!=drawable) return drawable.getNativeWindow().lockSurface();
590 return NativeWindow.LOCK_SURFACE_NOT_READY;
591 }
592
593 public synchronized void unlockSurface() {
594 if(null!=drawable) drawable.getNativeWindow().unlockSurface();
595 else throw new NativeWindowException("NEWT-GLWindow not locked");
596 }
597
598 public synchronized boolean isSurfaceLocked() {
599 if(null!=drawable) return drawable.getNativeWindow().isSurfaceLocked();
600 return false;
601 }
602
603 public synchronized Exception getLockedStack() {
604 if(null!=drawable) return drawable.getNativeWindow().getLockedStack();
605 return null;
606 }
607
608 public long getWindowHandle() {
609 if(null!=drawable) return drawable.getNativeWindow().getWindowHandle();
610 return super.getWindowHandle();
611 }
612
613 public long getSurfaceHandle() {
614 if(null!=drawable) return drawable.getNativeWindow().getSurfaceHandle();
615 return super.getSurfaceHandle();
616 }
617
618 //----------------------------------------------------------------------
619 // GLDrawable methods that are not really needed
620 //
621
622 public GLContext createContext(GLContext shareWith) {
623 return drawable.createContext(shareWith);
624 }
625
626 public void setRealized(boolean realized) {
627 }
628
629 public GLCapabilities getChosenGLCapabilities() {
630 if (drawable == null) {
631 throw new GLException("No drawable yet");
632 }
633
634 return drawable.getChosenGLCapabilities();
635 }
636
637 public GLProfile getGLProfile() {
638 if (drawable == null) {
639 throw new GLException("No drawable yet");
640 }
641
642 return drawable.getGLProfile();
643 }
644
645 //----------------------------------------------------------------------
646 // Internals only below this point
647 //
648
649 private void shouldNotCallThis() {
650 throw new NativeWindowException("Should not call this");
651 }
652}
http://JogAmp.org git info: FAQ, tutorial and man pages.