From b7252ec43e5e658a561d380bed882666d8e47f55 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Mon, 9 Jan 2012 17:53:36 +0100
Subject: SWT GLCanvas: Java 1.5 clean (No @override for interfaces); Add
 license header; Remove dummy comments

---
 .../classes/com/jogamp/opengl/swt/GLCanvas.java    | 549 +++++++++++++++++++++
 1 file changed, 549 insertions(+)
 create mode 100644 src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java

(limited to 'src/jogl/classes/com/jogamp/opengl/swt')

diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
new file mode 100644
index 000000000..689047235
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java
@@ -0,0 +1,549 @@
+/**
+ * Copyright 2011 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:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice, this list of
+ *       conditions and the following disclaimer.
+ *
+ *    2. Redistributions 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.opengl.swt;
+
+import javax.media.nativewindow.AbstractGraphicsDevice;
+import javax.media.nativewindow.NativeSurface;
+import javax.media.nativewindow.ProxySurface;
+import javax.media.opengl.GL;
+import javax.media.opengl.GLAnimatorControl;
+import javax.media.opengl.GLAutoDrawable;
+import javax.media.opengl.GLCapabilities;
+import javax.media.opengl.GLCapabilitiesChooser;
+import javax.media.opengl.GLCapabilitiesImmutable;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLDrawable;
+import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLEventListener;
+import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
+import javax.media.opengl.GLRunnable;
+import javax.media.opengl.Threading;
+
+import jogamp.nativewindow.swt.SWTAccessor;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLDrawableHelper;
+import jogamp.opengl.ThreadingImpl;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import com.jogamp.common.util.locks.LockFactory;
+import com.jogamp.common.util.locks.RecursiveLock;
+
+/**
+ * Native SWT Canvas implementing GLAutoDrawable
+ */
+public class GLCanvas extends Canvas implements GLAutoDrawable {
+
+   /*
+    * Flag for whether the SWT thread should be used for OpenGL calls when in single-threaded mode. This is controlled
+    * by the setting of the threading mode to worker (do not use SWT thread), awt (use SWT thread), or false (always use
+    * calling thread).
+    * 
+    * @see Threading
+    * 
+    * Now done dynamically to avoid early loading of gluegen library.
+    */
+   //private static final boolean useSWTThread = ThreadingImpl.getMode() != ThreadingImpl.WORKER;
+
+   /* GL Stuff */
+   private final GLDrawableHelper drawableHelper = new GLDrawableHelper();
+   private GLDrawable drawable;
+   private GLContext context;
+
+   /* Native window surface */
+   private AbstractGraphicsDevice device;
+   private final long nativeWindowHandle;
+   private final ProxySurface proxySurface;
+
+   /* Construction parameters stored for GLAutoDrawable accessor methods */
+   private int ctxCreationFlags = 0;
+   
+   private final GLCapabilitiesImmutable glCapsRequested;
+
+   /*
+    * Lock for access to GLDrawable, as used in GLCanvas,
+    */
+   private final RecursiveLock lock = LockFactory.createRecursiveLock();
+
+   /* Flag indicating whether an unprocessed reshape is pending. */
+   private volatile boolean sendReshape;
+
+   /*
+    * Invokes init(...) on all GLEventListeners. Assumes context is current when run.
+    */
+   private final Runnable initAction = new Runnable() {
+      public void run() {
+         drawableHelper.init(GLCanvas.this);
+      }
+   };
+
+   /*
+    * Action to handle display in OpenGL, also processes reshape since they should be done at the same time.
+    * 
+    * Assumes GLContext is current when run.
+    */
+   private final Runnable displayAction = new Runnable() {
+      public void run() {
+         if (sendReshape) {
+            drawableHelper.reshape(GLCanvas.this, 0, 0, getWidth(), getHeight());
+            sendReshape = false;
+         }
+         drawableHelper.display(GLCanvas.this);
+      }
+   };
+
+   /* Action to make specified context current prior to running displayAction */
+   private final Runnable makeCurrentAndDisplayAction = new Runnable() {
+      public void run() {
+         drawableHelper.invokeGL(drawable, context, displayAction, initAction);
+      }
+   };
+
+   /* Swaps buffers, assuming the GLContext is current */
+   private final Runnable swapBuffersAction = new Runnable() {
+      public void run() {
+         drawable.swapBuffers();
+      }
+   };
+
+   /* Swaps buffers, making the GLContext current first */
+   private final Runnable makeCurrentAndSwapBuffersAction = new Runnable() {
+      public void run() {
+         drawableHelper.invokeGL(drawable, context, swapBuffersAction, initAction);
+      }
+   };
+
+   /*
+    * Disposes of OpenGL resources
+    */
+   private final Runnable disposeGLAction = new Runnable() {
+      public void run() {
+         drawableHelper.dispose(GLCanvas.this);
+
+         if (null != context) {
+            context.makeCurrent(); // implicit wait for lock ..
+            context.destroy();
+            context = null;
+         }
+
+         if (null != drawable) {
+            drawable.setRealized(false);
+            drawable = null;
+         }
+      }
+   };
+
+   private final Runnable makeCurrentAndDisposeGLAction = new Runnable() {
+      public void run() {
+         drawableHelper.invokeGL(drawable, context, disposeGLAction, null);
+      }
+   };
+
+   private final Runnable disposeGraphicsDeviceAction = new Runnable() {
+      public void run() {
+         if (null != device) {
+            device.close();
+            device = null;
+         }
+      }
+   };
+
+   /**
+    * Creates a new SWT GLCanvas.
+    * 
+    * @param parent
+    *           Required (non-null) parent Composite.
+    * @param style
+    *           Optional SWT style bit-field. The {@link SWT#NO_BACKGROUND} bit is set before passing this up to the
+    *           Canvas constructor, so OpenGL handles the background.
+    * @param caps
+    *           Optional GLCapabilities. If not provided, the default capabilities for the default GLProfile for the
+    *           graphics device determined by the parent Composite are used. Note that the GLCapabilities that are
+    *           actually used may differ based on the capabilities of the graphics device.
+    * @param chooser
+    *           Optional GLCapabilitiesChooser to customize the selection of the used GLCapabilities based on the
+    *           requested GLCapabilities, and the available capabilities of the graphics device.
+    * @param shareWith
+    *           Optional GLContext to share state (textures, vbos, shaders, etc.) with.
+    */
+   public GLCanvas(final Composite parent, final int style, final GLCapabilities caps,
+         final GLCapabilitiesChooser chooser, final GLContext shareWith) {
+      /* NO_BACKGROUND required to avoid clearing bg in native SWT widget (we do this in the GL display) */
+      super(parent, style | SWT.NO_BACKGROUND);
+
+      SWTAccessor.setRealized(this, true);
+
+      /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */
+      device = SWTAccessor.getDevice(this);
+      /* Native handle for the control, used to associate with GLContext */
+      nativeWindowHandle = SWTAccessor.getWindowHandle(this);
+
+      /* Select default GLCapabilities if none was provided, otherwise clone provided caps to ensure safety */
+      final GLCapabilitiesImmutable fixedCaps = (caps == null) ? new GLCapabilities(GLProfile.getDefault(device))
+            : (GLCapabilitiesImmutable) caps.cloneMutable();
+      glCapsRequested = fixedCaps;
+      
+      final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(fixedCaps.getGLProfile());
+
+      /* Create a NativeWindow proxy for the SWT canvas */
+      proxySurface = glFactory.createProxySurface(device, nativeWindowHandle, fixedCaps, chooser);
+
+      /* Associate a GL surface with the proxy */
+      drawable = glFactory.createGLDrawable(proxySurface);
+      drawable.setRealized(true);
+
+      context = drawable.createContext(shareWith);
+
+      /* Register SWT listeners (e.g. PaintListener) to render/resize GL surface. */
+      /* TODO: verify that these do not need to be manually de-registered when destroying the SWT component */
+      addPaintListener(new PaintListener() {
+         public void paintControl(final PaintEvent arg0) {
+            if (!drawableHelper.isExternalAnimatorAnimating()) {
+               display();
+            }
+         }
+      });
+      
+      addControlListener(new ControlAdapter() {
+         @Override
+         public void controlResized(final ControlEvent arg0) {
+            /* Mark for OpenGL reshape next time the control is painted */
+            sendReshape = true;
+         }
+      });
+   }
+
+   public void addGLEventListener(final GLEventListener arg0) {
+      drawableHelper.addGLEventListener(arg0);
+   }
+
+   public void addGLEventListener(final int arg0, final GLEventListener arg1) throws IndexOutOfBoundsException {
+      drawableHelper.addGLEventListener(arg0, arg1);
+   }
+
+   /**
+    * {@inheritDoc}
+    * <p>
+    * Also disposes of the SWT component.
+    */
+   public void destroy() {
+      drawable.setRealized(false);
+      dispose();
+   }
+
+   public void display() {
+      runInGLThread(makeCurrentAndDisplayAction, displayAction);
+   }
+
+   public GLAnimatorControl getAnimator() {
+      return drawableHelper.getAnimator();
+   }
+
+   public boolean getAutoSwapBufferMode() {
+      return drawableHelper.getAutoSwapBufferMode();
+   }
+
+   public GLContext getContext() {
+      return context;
+   }
+
+   public int getContextCreationFlags() {
+      return ctxCreationFlags;
+   }
+
+   public GL getGL() {
+      final GLContext ctx = getContext();
+      return (ctx == null) ? null : ctx.getGL();
+   }
+
+   public void invoke(final boolean wait, final GLRunnable run) {
+      /* Queue task for running during the next display(). */
+      drawableHelper.invoke(this, wait, run);
+   }
+
+   public void removeGLEventListener(final GLEventListener arg0) {
+      drawableHelper.removeGLEventListener(arg0);
+   }
+
+   public void setAnimator(final GLAnimatorControl arg0) throws GLException {
+      drawableHelper.setAnimator(arg0);
+   }
+
+   public void setAutoSwapBufferMode(final boolean arg0) {
+      drawableHelper.setAutoSwapBufferMode(arg0);
+   }
+
+   public void setContext(final GLContext ctx) {
+      this.context = ctx;
+      if (ctx instanceof GLContextImpl) {
+         ((GLContextImpl) ctx).setContextCreationFlags(ctxCreationFlags);
+      }
+   }
+
+   public void setContextCreationFlags(final int arg0) {
+      ctxCreationFlags = arg0;
+   }
+
+   public GL setGL(final GL arg0) {
+      final GLContext ctx = getContext();
+      if (ctx != null) {
+         ctx.setGL(arg0);
+         return arg0;
+      }
+      return null;
+   }
+
+   public GLContext createContext(final GLContext arg0) {
+      lock.lock();
+      try {
+         final GLDrawable drawable = this.drawable;
+         return (drawable != null) ? drawable.createContext(arg0) : null;
+      } finally {
+         lock.unlock();
+      }
+   }
+
+   public GLCapabilitiesImmutable getChosenGLCapabilities() {
+      return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getChosenCapabilities();
+   }
+
+   /**
+    * Accessor for the GLCapabilities that were requested (via the constructor parameter).
+    * 
+    * @return Non-null GLCapabilities.
+    */
+   public GLCapabilitiesImmutable getRequestedGLCapabilities() {
+      return (GLCapabilitiesImmutable)proxySurface.getGraphicsConfiguration().getRequestedCapabilities();
+   }
+
+   public GLDrawableFactory getFactory() {
+      lock.lock();
+      try {
+         final GLDrawable drawable = this.drawable;
+         return (drawable != null) ? drawable.getFactory() : null;
+      } finally {
+         lock.unlock();
+      }
+   }
+
+   public GLProfile getGLProfile() {
+      return glCapsRequested.getGLProfile();
+   }
+
+   public long getHandle() {
+      lock.lock();
+      try {
+         final GLDrawable drawable = this.drawable;
+         return (drawable != null) ? drawable.getHandle() : 0;
+      } finally {
+         lock.unlock();
+      }
+   }
+
+   public int getHeight() {
+      return getClientArea().height;
+   }
+
+   public NativeSurface getNativeSurface() {
+      lock.lock();
+      try {
+         final GLDrawable drawable = this.drawable;
+         return (drawable != null) ? drawable.getNativeSurface() : null;
+      } finally {
+         lock.unlock();
+      }
+   }
+
+   public int getWidth() {
+      return getClientArea().width;
+   }
+
+   public boolean isRealized() {
+      lock.lock();
+      try {
+         final GLDrawable drawable = this.drawable;
+         return (drawable != null) ? drawable.isRealized() : false;
+      } finally {
+         lock.unlock();
+      }
+   }
+
+   public void setRealized(final boolean arg0) {
+      /* Intentionally empty */
+   }
+
+   public void swapBuffers() throws GLException {
+      runInGLThread(makeCurrentAndSwapBuffersAction, swapBuffersAction);
+   }
+
+   // FIXME: API of update() method ?
+   public void update() {
+    // FIXME:     display();
+   }
+
+   public void dispose() {
+      lock.lock();
+      try {
+         final Display display = getDisplay();
+
+         if (null != context) {
+            boolean animatorPaused = false;
+            final GLAnimatorControl animator = getAnimator();
+            if (null != animator) {
+               // can't remove us from animator for recreational addNotify()
+               animatorPaused = animator.pause();
+            }
+            if (Threading.isSingleThreaded() && !Threading.isOpenGLThread()) {
+               runInDesignatedGLThread(makeCurrentAndDisposeGLAction);
+            } else if (context.isCreated()) {
+               drawableHelper.invokeGL(drawable, context, disposeGLAction, null);
+            }
+
+            if (animatorPaused) {
+               animator.resume();
+            }
+         }
+         if (display.getThread() == Thread.currentThread())
+            disposeGraphicsDeviceAction.run();
+         else
+            display.syncExec(disposeGraphicsDeviceAction);
+      } finally {
+         lock.unlock();
+      }
+      super.dispose();
+   }
+
+   /**
+    * Determines whether the current thread is the appropriate thread to use the GLContext in. If we are using one of
+    * the single-threaded policies in {@link Threading}, than this is either the SWT event dispatch thread, or the
+    * OpenGL worker thread depending on the state of {@link #useSWTThread}. Otherwise this always returns true because
+    * the threading model is user defined.
+    * <p>
+    * TODO: should this be moved to {@link Threading}?
+    * 
+    * @return true if the calling thread is the correct thread to execute OpenGL calls in, false otherwise.
+    */
+   protected boolean isRenderThread() {
+      if (Threading.isSingleThreaded()) {
+         if (ThreadingImpl.getMode() != ThreadingImpl.WORKER) {
+            final Display display = getDisplay();
+            return display != null && display.getThread() == Thread.currentThread();
+         }
+         return Threading.isOpenGLThread();
+      }
+      /*
+       * For multi-threaded rendering, the render thread is not defined...
+       */
+      return true;
+   }
+
+   /**
+    * Runs the specified action in the designated OpenGL thread. If the current thread is designated, then the
+    * syncAction is run synchronously, otherwise the asyncAction is dispatched to the appropriate worker thread.
+    * 
+    * @param asyncAction
+    *           The non-null action to dispatch to an OpenGL worker thread. This action should not assume that a
+    *           GLContext is current when invoked.
+    * @param syncAction
+    *           The non-null action to run synchronously if the current thread is designated to handle OpenGL calls.
+    *           This action may assume the GLContext is current.
+    */
+   private void runInGLThread(final Runnable asyncAction, final Runnable syncAction) {
+      if (Threading.isSingleThreaded() && !isRenderThread()) {
+         /* Run in designated GL thread */
+         runInDesignatedGLThread(asyncAction);
+      } else {
+         /* Run in current thread... */
+         drawableHelper.invokeGL(drawable, context, syncAction, initAction);
+      }
+   }
+
+   /**
+    * Dispatches the specified runnable to the appropriate OpenGL worker thread (either the SWT event dispatch thread,
+    * or the OpenGL worker thread depending on the state of {@link #useSWTThread}).
+    * 
+    * @param makeCurrentAndRunAction
+    *           The non-null action to dispatch.
+    */
+   private void runInDesignatedGLThread(final Runnable makeCurrentAndRunAction) {
+      if (ThreadingImpl.getMode() != ThreadingImpl.WORKER) {
+         final Display display = getDisplay();
+         assert display.getThread() != Thread.currentThread() : "Incorrect use of thread dispatching.";
+         display.syncExec(makeCurrentAndRunAction);
+      } else {
+         Threading.invokeOnOpenGLThread(makeCurrentAndRunAction);
+      }
+   }
+
+   
+   public static void main(final String[] args) {
+      final Display display = new Display();
+      final Shell shell = new Shell(display);
+      shell.setSize(800,600);
+      shell.setLayout(new FillLayout());
+
+      final GLCanvas canvas = new GLCanvas(shell,
+            0, null, null, null);
+
+      canvas.addGLEventListener(new GLEventListener() {
+         
+         public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+            System.out.println("Reshape");
+         }
+         
+         public void init(final GLAutoDrawable drawable) {
+            System.out.println("Init");
+         }
+         
+         public void dispose(final GLAutoDrawable drawable) {
+            System.out.println("Dispose");
+         }
+         
+         public void display(final GLAutoDrawable drawable) {
+            System.out.println("Display");
+         }
+      });
+      shell.setSize(500, 500);
+      shell.open();
+      while (!shell.isDisposed()) {
+         if (!display.readAndDispatch())
+            display.sleep();
+      }
+      display.dispose();
+   }
+}
-- 
cgit v1.2.3