All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jogamp.newt.opengl.GLWindow Maven / Gradle / Ivy

/*
 * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
 * Copyright (c) 2010 JogAmp Community. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistribution of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistribution in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 */

package com.jogamp.newt.opengl;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;

import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
import com.jogamp.nativewindow.CapabilitiesChooser;
import com.jogamp.nativewindow.CapabilitiesImmutable;
import com.jogamp.nativewindow.NativeSurface;
import com.jogamp.nativewindow.NativeWindow;
import com.jogamp.nativewindow.NativeWindowException;
import com.jogamp.nativewindow.SurfaceUpdatedListener;
import com.jogamp.nativewindow.util.InsetsImmutable;
import com.jogamp.nativewindow.util.Point;
import com.jogamp.nativewindow.util.Rectangle;
import com.jogamp.opengl.FPSCounter;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GL4ES3;
import com.jogamp.opengl.GLAnimatorControl;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawable;
import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLES2;
import com.jogamp.opengl.GLES3;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.GLRunnable;
import com.jogamp.opengl.GLSharedContextSetter;

import jogamp.newt.WindowImpl;
import jogamp.opengl.GLAutoDrawableBase;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableImpl;

import com.jogamp.common.GlueGenVersion;
import com.jogamp.common.util.VersionUtil;
import com.jogamp.common.util.locks.RecursiveLock;
import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
import com.jogamp.newt.Window;
import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.event.GestureHandler;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseListener;
import com.jogamp.newt.event.NEWTEvent;
import com.jogamp.newt.event.NEWTEventConsumer;
import com.jogamp.newt.event.NEWTEventListener;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.opengl.JoglVersion;
import com.jogamp.opengl.GLStateKeeper;

/**
 * An implementation of {@link GLAutoDrawable} and {@link Window} interface,
 * using a delegated {@link Window} instance, which may be an aggregation (lifecycle: created and destroyed).
 * 

* This implementation supports {@link GLStateKeeper GL state preservation}, * hence {@link #isGLStatePreservationSupported()} returns true. *

*

* This implementation does not make the OpenGL context current
* before calling the various input EventListener callbacks, ie {@link MouseListener} etc.
* This design decision is made in favor of a more performant and simplified * implementation. Also the event dispatcher shall be implemented OpenGL agnostic.
* To be able to use OpenGL commands from within such input {@link NEWTEventListener},
* you can inject {@link GLRunnable} objects * via {@link #invoke(boolean, GLRunnable)} to the OpenGL command stream.
*

*

*

OpenGL Context Sharing
* To share a {@link GLContext} see the following note in the documentation overview: * context sharing * as well as {@link GLSharedContextSetter}. *

*/ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Window, NEWTEventConsumer, FPSCounter { private final WindowImpl window; /** * Constructor. Do not call this directly -- use {@link #create()} instead. */ protected GLWindow(final Window window) { super(null, null, false /* always handle device lifecycle ourselves */); this.window = (WindowImpl) window; this.window.setWindowDestroyNotifyAction( new Runnable() { @Override public void run() { defaultWindowDestroyNotifyOp(); } } ); window.addWindowListener(new WindowAdapter() { @Override public void windowRepaint(final WindowUpdateEvent e) { defaultWindowRepaintOp(); } @Override public void windowResized(final WindowEvent e) { defaultWindowResizedOp(getSurfaceWidth(), getSurfaceHeight()); } }); this.window.setLifecycleHook(new GLLifecycleHook()); } @Override public final Object getUpstreamWidget() { return window; } @Override public final RecursiveLock getUpstreamLock() { return window.getLock(); } /** * Creates a new GLWindow attaching a new Window referencing a * new default Screen and default Display with the given GLCapabilities. *

* The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} * and {@link Screen#removeReference()}. *

* The default Display will be reused if already instantiated. */ public static GLWindow create(final GLCapabilitiesImmutable caps) { return new GLWindow(NewtFactory.createWindow(caps)); } /** * Creates a new GLWindow attaching a new Window referencing the given Screen * with the given GLCapabilities. *

* The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} * and {@link Screen#removeReference()}. *

*/ public static GLWindow create(final Screen screen, final GLCapabilitiesImmutable caps) { return new GLWindow(NewtFactory.createWindow(screen, caps)); } /** * Creates a new GLWindow attaching the given window. *

* The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} * and {@link Screen#removeReference()}. *

*/ public static GLWindow create(final Window window) { return new GLWindow(window); } /** * Creates a new GLWindow attaching a new child Window * of the given parentNativeWindow with the given GLCapabilities. *

* The Display/Screen will be compatible with the parentNativeWindow, * or even identical in case it's a Newt Window. * An already instantiated compatible Display will be reused. *

*

* The lifecycle of this Window's Screen and Display is handled via {@link Screen#addReference()} * and {@link Screen#removeReference()}. *

*/ public static GLWindow create(final NativeWindow parentNativeWindow, final GLCapabilitiesImmutable caps) { return new GLWindow(NewtFactory.createWindow(parentNativeWindow, caps)); } //---------------------------------------------------------------------- // WindowClosingProtocol implementation // @Override public WindowClosingMode getDefaultCloseOperation() { return window.getDefaultCloseOperation(); } @Override public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) { return window.setDefaultCloseOperation(op); } //---------------------------------------------------------------------- // Window Access // @Override public CapabilitiesChooser setCapabilitiesChooser(final CapabilitiesChooser chooser) { return window.setCapabilitiesChooser(chooser); } @Override public final CapabilitiesImmutable getChosenCapabilities() { final GLDrawable _drawable = drawable; return null != _drawable ? _drawable.getChosenGLCapabilities() : window.getChosenCapabilities(); } @Override public final CapabilitiesImmutable getRequestedCapabilities() { return window.getRequestedCapabilities(); } @Override public final Window getDelegatedWindow() { return window.getDelegatedWindow(); } @Override public final NativeWindow getParent() { return window.getParent(); } @Override public final Screen getScreen() { return window.getScreen(); } @Override public final MonitorDevice getMainMonitor() { return window.getMainMonitor(); } @Override public final void setTitle(final String title) { window.setTitle(title); } @Override public final String getTitle() { return window.getTitle(); } @Override public final boolean isPointerVisible() { return window.isPointerVisible(); } @Override public final void setPointerVisible(final boolean mouseVisible) { window.setPointerVisible(mouseVisible); } @Override public final PointerIcon getPointerIcon() { return window.getPointerIcon(); } @Override public final void setPointerIcon(final PointerIcon pi) { window.setPointerIcon(pi); } @Override public final boolean isPointerConfined() { return window.isPointerConfined(); } @Override public final void confinePointer(final boolean grab) { window.confinePointer(grab); } @Override public final void setUndecorated(final boolean value) { window.setUndecorated(value); } @Override public final void warpPointer(final int x, final int y) { window.warpPointer(x, y); } @Override public final boolean isUndecorated() { return window.isUndecorated(); } @Override public final void setAlwaysOnTop(final boolean value) { window.setAlwaysOnTop(value); } @Override public final boolean isAlwaysOnTop() { return window.isAlwaysOnTop(); } @Override public final void setFocusAction(final FocusRunnable focusAction) { window.setFocusAction(focusAction); } @Override public void setKeyboardFocusHandler(final KeyListener l) { window.setKeyboardFocusHandler(l); } @Override public final void requestFocus() { window.requestFocus(); } @Override public final void requestFocus(final boolean wait) { window.requestFocus(wait); } @Override public boolean hasFocus() { return window.hasFocus(); } @Override public final InsetsImmutable getInsets() { return window.getInsets(); } @Override public final int getX() { return window.getX(); } @Override public final int getY() { return window.getY(); } @Override public final int getWidth() { return window.getWidth(); } @Override public final int getHeight() { return window.getHeight(); } @Override public final Rectangle getBounds() { return window.getBounds(); } @Override public final int getSurfaceWidth() { return window.getSurfaceWidth(); } @Override public final int getSurfaceHeight() { return window.getSurfaceHeight(); } @Override public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) { return window.convertToWindowUnits(pixelUnitsAndResult); } @Override public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) { return window.convertToPixelUnits(windowUnitsAndResult); } @Override public final boolean setSurfaceScale(final float[] pixelScale) { return window.setSurfaceScale(pixelScale); } @Override public final float[] getRequestedSurfaceScale(final float[] result) { return window.getRequestedSurfaceScale(result); } @Override public final float[] getCurrentSurfaceScale(final float[] result) { return window.getCurrentSurfaceScale(result); } @Override public final float[] getMinimumSurfaceScale(final float[] result) { return window.getMinimumSurfaceScale(result); } @Override public final float[] getMaximumSurfaceScale(final float[] result) { return window.getMaximumSurfaceScale(result); } @Override public final float[] getPixelsPerMM(final float[] ppmmStore) { return window.getPixelsPerMM(ppmmStore); } @Override public final void setPosition(final int x, final int y) { window.setPosition(x, y); } @Override public void setTopLevelPosition(final int x, final int y) { window.setTopLevelPosition(x, y); } @Override public final boolean setFullscreen(final boolean fullscreen) { return window.setFullscreen(fullscreen); } @Override public boolean setFullscreen(final List monitors) { return window.setFullscreen(monitors); } @Override public final boolean isFullscreen() { return window.isFullscreen(); } @Override public final boolean isVisible() { return window.isVisible(); } @Override public final String toString() { return "NEWT-GLWindow[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + ", \n\tContext: " + context + ", \n\tWindow: "+window+ /** ", \n\tFactory: "+factory+ */ "]"; } @Override public final ReparentOperation reparentWindow(final NativeWindow newParent, final int x, final int y, final int hints) { return window.reparentWindow(newParent, x, y, hints); } @Override public final boolean removeChild(final NativeWindow win) { return window.removeChild(win); } @Override public final boolean addChild(final NativeWindow win) { return window.addChild(win); } //---------------------------------------------------------------------- // Window.LifecycleHook Implementation // @Override public final void destroy() { window.destroy(); } @Override public void setWindowDestroyNotifyAction(final Runnable r) { window.setWindowDestroyNotifyAction(r); } @Override public final void setVisible(final boolean visible) { window.setVisible(visible); } @Override public void setVisible(final boolean wait, final boolean visible) { window.setVisible(wait, visible); } @Override public final void setSize(final int width, final int height) { window.setSize(width, height); } @Override public final void setSurfaceSize(final int pixelWidth, final int pixelHeight) { window.setSurfaceSize(pixelWidth, pixelHeight); } @Override public void setTopLevelSize(final int width, final int height) { window.setTopLevelSize(width, height); } @Override public final boolean isNativeValid() { return window.isNativeValid(); } @Override public Point getLocationOnScreen(final Point storage) { return window.getLocationOnScreen(storage); } // Hide methods here .. protected class GLLifecycleHook implements WindowImpl.LifecycleHook { @Override public void preserveGLStateAtDestroy(final boolean value) { GLWindow.this.preserveGLStateAtDestroy(value); } @Override public synchronized void destroyActionPreLock() { // nop } @Override public synchronized void destroyActionInLock() { if(Window.DEBUG_IMPLEMENTATION) { final String msg = "GLWindow.destroy() "+WindowImpl.getThreadName()+", start"; System.err.println(msg); //Exception e1 = new Exception(msg); //e1.printStackTrace(); } destroyImplInLock(); if(Window.DEBUG_IMPLEMENTATION) { System.err.println("GLWindow.destroy() "+WindowImpl.getThreadName()+", fin"); } } @Override public synchronized void resetCounter() { if(Window.DEBUG_IMPLEMENTATION) { System.err.println("GLWindow.resetCounter() "+WindowImpl.getThreadName()); } GLWindow.this.resetFPSCounter(); final GLAnimatorControl animator = GLWindow.this.getAnimator(); if( null != animator ) { animator.resetFPSCounter(); } } @Override public synchronized void setVisibleActionPost(final boolean visible, final boolean nativeWindowCreated) { long t0; if(Window.DEBUG_IMPLEMENTATION) { t0 = System.nanoTime(); System.err.println("GLWindow.setVisibleActionPost("+visible+", "+nativeWindowCreated+") "+WindowImpl.getThreadName()+", start"); } else { t0 = 0; } if (null == drawable && visible && 0 != window.getWindowHandle() && 0() { @Override public Object run() { if( anim.isAnimating() && null != animThread ) { try { animThread.stop(); } catch(final Throwable t) { if( DEBUG ) { System.err.println("Caught "+t.getClass().getName()+": "+t.getMessage()); t.printStackTrace(); } } } return null; } } ); } } } } //---------------------------------------------------------------------- // OpenGL-related methods and state // @Override public void display() { if( !isNativeValid() || !isVisible() ) { return; } if(sendDestroy || ( window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED ) ) { sendDestroy=false; destroy(); return; } final boolean done; final RecursiveLock lock = window.getLock(); lock.lock(); // sync: context/drawable could have been recreated/destroyed while animating try { if( null != context ) { // surface is locked/unlocked implicit by context's makeCurrent/release helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); done = true; } else { done = false; } } finally { lock.unlock(); } if( !done && ( 0 < getSurfaceWidth() && 0 < getSurfaceHeight() ) ) { // retry drawable and context creation, will itself issue resize -> display setVisible(true); } } /** * {@inheritDoc} *

* GLWindow supports GL state preservation, hence returns true. *

*/ @Override public final boolean isGLStatePreservationSupported() { return true; } //---------------------------------------------------------------------- // GLDrawable methods // private GLDrawableFactory factory; @Override public final GLDrawableFactory getFactory() { return factory; } @Override public final void swapBuffers() throws GLException { defaultSwapBuffers(); } //---------------------------------------------------------------------- // NEWTEventConsumer // @Override public boolean consumeEvent(final NEWTEvent event) { return window.consumeEvent(event); } //---------------------------------------------------------------------- // Window completion // @Override public final void windowRepaint(final int x, final int y, final int width, final int height) { window.windowRepaint(x, y, width, height); } @Override public final void enqueueEvent(final boolean wait, final com.jogamp.newt.event.NEWTEvent event) { window.enqueueEvent(wait, event); } @Override public final void runOnEDTIfAvail(final boolean wait, final Runnable task) { window.runOnEDTIfAvail(wait, task); } @Override public void sendWindowEvent(final int eventType) { window.sendWindowEvent(eventType); } @Override public final WindowListener getWindowListener(final int index) { return window.getWindowListener(index); } @Override public final WindowListener[] getWindowListeners() { return window.getWindowListeners(); } @Override public final void removeWindowListener(final WindowListener l) { window.removeWindowListener(l); } @Override public final void addWindowListener(final WindowListener l) { window.addWindowListener(l); } @Override public final void addWindowListener(final int index, final WindowListener l) throws IndexOutOfBoundsException { window.addWindowListener(index, l); } @Override public final void setKeyboardVisible(final boolean visible) { window.setKeyboardVisible(visible); } @Override public final boolean isKeyboardVisible() { return window.isKeyboardVisible(); } @Override public final void addKeyListener(final KeyListener l) { window.addKeyListener(l); } @Override public final void addKeyListener(final int index, final KeyListener l) { window.addKeyListener(index, l); } @Override public final void removeKeyListener(final KeyListener l) { window.removeKeyListener(l); } @Override public final KeyListener getKeyListener(final int index) { return window.getKeyListener(index); } @Override public final KeyListener[] getKeyListeners() { return window.getKeyListeners(); } @Override public final void addMouseListener(final MouseListener l) { window.addMouseListener(l); } @Override public final void addMouseListener(final int index, final MouseListener l) { window.addMouseListener(index, l); } @Override public final void removeMouseListener(final MouseListener l) { window.removeMouseListener(l); } @Override public final MouseListener getMouseListener(final int index) { return window.getMouseListener(index); } @Override public final MouseListener[] getMouseListeners() { return window.getMouseListeners(); } @Override public void setDefaultGesturesEnabled(final boolean enable) { window.setDefaultGesturesEnabled(enable); } @Override public boolean areDefaultGesturesEnabled() { return window.areDefaultGesturesEnabled(); } @Override public final void addGestureHandler(final GestureHandler gh) { window.addGestureHandler(gh); } @Override public final void addGestureHandler(final int index, final GestureHandler gh) { window.addGestureHandler(index, gh); } @Override public final void removeGestureHandler(final GestureHandler gh) { window.removeGestureHandler(gh); } @Override public final void addGestureListener(final GestureHandler.GestureListener gl) { window.addGestureListener(-1, gl); } @Override public final void addGestureListener(final int index, final GestureHandler.GestureListener gl) { window.addGestureListener(index, gl); } @Override public final void removeGestureListener(final GestureHandler.GestureListener gl) { window.removeGestureListener(gl); } //---------------------------------------------------------------------- // NativeWindow completion // @Override public final int lockSurface() throws NativeWindowException, RuntimeException { return window.lockSurface(); } @Override public final void unlockSurface() { window.unlockSurface(); } @Override public final boolean isSurfaceLockedByOtherThread() { return window.isSurfaceLockedByOtherThread(); } @Override public final Thread getSurfaceLockOwner() { return window.getSurfaceLockOwner(); } @Override public final boolean surfaceSwap() { return window.surfaceSwap(); } @Override public final void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) { window.removeSurfaceUpdatedListener(l); } @Override public final void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) { window.addSurfaceUpdatedListener(l); } @Override public final void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException { window.addSurfaceUpdatedListener(index, l); } @Override public final void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) { window.surfaceUpdated(updater, ns, when); } @Override public final long getWindowHandle() { return window.getWindowHandle(); } @Override public final long getSurfaceHandle() { return window.getSurfaceHandle(); } @Override public final AbstractGraphicsConfiguration getGraphicsConfiguration() { return window.getGraphicsConfiguration(); } @Override public final long getDisplayHandle() { return window.getDisplayHandle(); } @Override public final int getScreenIndex() { return window.getScreenIndex(); } /** * A most simple JOGL AWT test entry */ public static void main(final String args[]) { final boolean forceES2; final boolean forceES3; final boolean forceGL3; final boolean forceGL4ES3; { boolean _forceES2 = false; boolean _forceES3 = false; boolean _forceGL3 = false; boolean _forceGL4ES3 = false; if( null != args ) { for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy