Browse Source

Merge remote-tracking branch 'upstream/master'

Conflicts:
	jme3-core/src/main/java/com/jme3/light/AmbientLight.java
	jme3-core/src/main/java/com/jme3/light/DirectionalLight.java
	jme3-core/src/main/java/com/jme3/light/PointLight.java
	jme3-core/src/main/java/com/jme3/light/SpotLight.java
Daniel Johansson 10 năm trước cách đây
mục cha
commit
c32ac172fb

+ 1 - 1
.travis.yml

@@ -25,7 +25,7 @@ install:
 script:
   - ./gradlew check
   - ./gradlew createZipDistribution
-  - "[ $TRAVIS_BRANCH == 'master' ] && [ $TRAVIS_PULL_REQUEST == 'false' ] && ./gradlew uploadArchives;"
+  - [ $TRAVIS_BRANCH == 'master' ] && [ $TRAVIS_PULL_REQUEST == 'false' ] && ./gradlew uploadArchives || :
 
 before_deploy:
   - export RELEASE_DIST=$(ls build/distributions/*.zip)

+ 5 - 13
jme3-core/src/main/java/com/jme3/light/AmbientLight.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2012, 2015 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,23 +45,15 @@ import com.jme3.util.TempVars;
  * regardless of the model's location. The material's ambient color is
  * multiplied by the ambient light color to get the final ambient color of
  * an object.
- * 
+ *
  * @author Kirill Vainer
  */
 public class AmbientLight extends Light {
 
-    /**
-     * Default constructor for AmbientLight.
-     */
     public AmbientLight() {
     }
 
-    /**
-     * Constructor which allows setting of the color.
-     *
-     * @param color the color to apply to this light.
-     */
-    public AmbientLight(final ColorRGBA color) {
+    public AmbientLight(ColorRGBA color) {
         super(color);
     }
 
@@ -69,12 +61,12 @@ public class AmbientLight extends Light {
     public boolean intersectsBox(BoundingBox box, TempVars vars) {
         return true;
     }
-    
+
     @Override
     public boolean intersectsFrustum(Camera camera, TempVars vars) {
         return true;
     }
-    
+
     @Override
     public void computeLastDistance(Spatial owner) {
     }

+ 18 - 20
jme3-core/src/main/java/com/jme3/light/DirectionalLight.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2012, 2015 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -55,29 +55,27 @@ public class DirectionalLight extends Light {
     protected Vector3f direction = new Vector3f(0f, -1f, 0f);
 
     /**
-     * Default constructor for DirectionalLight. Direction will be defaulted to -1 on the Y axis.
+     * Creates a DirectionalLight
      */
     public DirectionalLight() {
     }
 
     /**
-     * Constructor which allows setting of the direction.
-     *
-     * @param direction the direction vector for the light.
+     * Creates a DirectionalLight with the given direction
+     * @param direction the light's direction
      */
-    public DirectionalLight(final Vector3f direction) {
-        this.direction = direction;
+    public DirectionalLight(Vector3f direction) {
+        setDirection(direction);
     }
 
     /**
-     * Constructor which allows setting of the color and direction.
-     *
-     * @param color the color to apply to this light.
-     * @param direction the direction vector for the light.
+     * Creates a DirectionalLight with the given direction and the given color
+     * @param direction the light's direction
+     * @param color the light's color
      */
-    public DirectionalLight(final ColorRGBA color, final Vector3f direction) {
+    public DirectionalLight(Vector3f direction, ColorRGBA color) {
         super(color);
-        this.direction = direction;
+        setDirection(direction);
     }
 
     @Override
@@ -87,10 +85,10 @@ public class DirectionalLight extends Light {
 
     /**
      * Returns the direction vector of the light.
-     * 
+     *
      * @return The direction vector of the light.
-     * 
-     * @see DirectionalLight#setDirection(com.jme3.math.Vector3f) 
+     *
+     * @see DirectionalLight#setDirection(com.jme3.math.Vector3f)
      */
     public Vector3f getDirection() {
         return direction;
@@ -101,10 +99,10 @@ public class DirectionalLight extends Light {
      * <p>
      * Represents the direction the light is shining.
      * (1, 0, 0) would represent light shining in the +X direction.
-     * 
+     *
      * @param dir the direction of the light.
      */
-    public void setDirection(Vector3f dir){
+    public final void setDirection(Vector3f dir){
         direction.set(dir);
         if (!direction.isUnitVector()) {
             direction.normalizeLocal();
@@ -115,12 +113,12 @@ public class DirectionalLight extends Light {
     public boolean intersectsBox(BoundingBox box, TempVars vars) {
         return true;
     }
-    
+
     @Override
     public boolean intersectsFrustum(Camera camera, TempVars vars) {
         return true;
     }
-    
+
     @Override
     public Type getType() {
         return Type.Directional;

+ 9 - 2
jme3-core/src/main/java/com/jme3/light/Light.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2012, 2015 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -94,7 +94,7 @@ public abstract class Light implements Savable, Cloneable {
         }
     }
 
-    protected ColorRGBA color = new ColorRGBA(1f,1f,1f,1f);
+    protected ColorRGBA color = new ColorRGBA(ColorRGBA.White);
     
     /**
      * Used in LightList for caching the distance 
@@ -115,6 +115,13 @@ public abstract class Light implements Savable, Cloneable {
     boolean frustumCheckNeeded = true;
     boolean intersectsFrustum  = false;
 
+    protected Light() {
+    }
+
+    protected Light(ColorRGBA color) {
+        setColor(color);
+    }
+
     /**
      * Default constructor for Light.
      */

+ 47 - 38
jme3-core/src/main/java/com/jme3/light/PointLight.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2012, 2015 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,7 +32,6 @@
 package com.jme3.light;
 
 import com.jme3.bounding.BoundingBox;
-import com.jme3.bounding.BoundingSphere;
 import com.jme3.bounding.BoundingVolume;
 import com.jme3.export.InputCapsule;
 import com.jme3.export.JmeExporter;
@@ -40,7 +39,6 @@ import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.FastMath;
-import com.jme3.math.Plane;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
 import com.jme3.scene.Spatial;
@@ -55,7 +53,7 @@ import java.io.IOException;
  * In addition to a position, point lights also have a radius which 
  * can be used to attenuate the influence of the light depending on the 
  * distance between the light and the effected object.
- * 
+ *
  */
 public class PointLight extends Light {
 
@@ -64,38 +62,49 @@ public class PointLight extends Light {
     protected float invRadius = 0;
 
     /**
-     * Default constructor for PointLight.
-     * <p>
-     *  <ul>
-     *      <li>Position will be defaulted to 0,0,0.</li>
-     *      <li>Radius will be defaulted to 0</li>
-     *  </ul>
-     * </p>
+     * Creates a PointLight
      */
     public PointLight() {
     }
 
     /**
-     * Constructor which allows setting of the color and position.
-     *
-     * @param color the color to apply to this light.
-     * @param position the position of the light.
+     * Creates a PointLight at the given position
+     * @param position the position in world space
      */
-    public PointLight(final ColorRGBA color, final Vector3f position) {
-        this(color, position, 0);
+    public PointLight(Vector3f position) {
+        setPosition(position);
     }
 
     /**
-     * Constructor which allows setting of the color, position and radius.
-     *
-     * @param color the color to apply to this light.
-     * @param position the position of the light.
-     * @param radius the radius of the light.
+     * Creates a PointLight at the given position and with the given color
+     * @param position the position in world space
+     * @param color the light color
      */
-    public PointLight(final ColorRGBA color, final Vector3f position, final float radius) {
+    public PointLight(Vector3f position, ColorRGBA color) {
         super(color);
-        this.position = position;
-        this.radius = radius;
+        setPosition(position);
+    }
+
+    /**
+     * Creates a PointLight at the given position, with the given color and the 
+     * given radius
+     * @param position the position in world space
+     * @param color the light color
+     * @param radius the light radius
+     */
+    public PointLight(Vector3f position, ColorRGBA color, float radius) {
+        this(position, color);
+        setRadius(radius);
+    }
+
+    /**
+     * Creates a PointLight at the given position, with the given radius
+     * @param position the position in world space
+     * @param radius the light radius
+     */
+    public PointLight(Vector3f position, float radius) {
+        this(position);
+        setRadius(radius);
     }
 
     @Override
@@ -110,10 +119,10 @@ public class PointLight extends Light {
 
     /**
      * Returns the world space position of the light.
-     * 
+     *
      * @return the world space position of the light.
-     * 
-     * @see PointLight#setPosition(com.jme3.math.Vector3f) 
+     *
+     * @see PointLight#setPosition(com.jme3.math.Vector3f)
      */
     public Vector3f getPosition() {
         return position;
@@ -121,17 +130,17 @@ public class PointLight extends Light {
 
     /**
      * Set the world space position of the light.
-     * 
+     *
      * @param position the world space position of the light.
      */
-    public void setPosition(Vector3f position) {
+    public final void setPosition(Vector3f position) {
         this.position.set(position);
     }
 
     /**
      * Returns the radius of the light influence. A radius of 0 means
      * the light has no attenuation.
-     * 
+     *
      * @return the radius of the light
      */
     public float getRadius() {
@@ -146,12 +155,12 @@ public class PointLight extends Light {
      * is greater than the light's radius, then the pixel will not be
      * effected by this light, if the distance is less than the radius, then
      * the magnitude of the influence is equal to distance / radius.
-     * 
+     *
      * @param radius the radius of the light influence.
-     * 
+     *
      * @throws IllegalArgumentException If radius is negative
      */
-    public void setRadius(float radius) {
+    public final void setRadius(float radius) {
         if (radius < 0) {
             throw new IllegalArgumentException("Light radius cannot be negative");
         }
@@ -183,11 +192,11 @@ public class PointLight extends Light {
         } else {
             // Sphere v. box collision
             return FastMath.abs(box.getCenter().x - position.x) < radius + box.getXExtent()
-                && FastMath.abs(box.getCenter().y - position.y) < radius + box.getYExtent()
-                && FastMath.abs(box.getCenter().z - position.z) < radius + box.getZExtent();
+                    && FastMath.abs(box.getCenter().y - position.y) < radius + box.getYExtent()
+                    && FastMath.abs(box.getCenter().z - position.z) < radius + box.getZExtent();
         }
     }
-    
+
     @Override
     public boolean intersectsFrustum(Camera camera, TempVars vars) {
         if (this.radius == 0) {
@@ -201,7 +210,7 @@ public class PointLight extends Light {
             return true;
         }
     }
-    
+
     @Override
     public void write(JmeExporter ex) throws IOException {
         super.write(ex);

+ 88 - 35
jme3-core/src/main/java/com/jme3/light/SpotLight.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2012 jMonkeyEngine
+ * Copyright (c) 2009-2012, 2015 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -45,22 +45,22 @@ import java.io.IOException;
 
 /**
  * Represents a spot light.
- * A spot light emmit a cone of light from a position and in a direction.
- * It can be used to fake torch lights or car's lights.
+ * A spot light emits a cone of light from a position and in a direction.
+ * It can be used to fake torch lights or cars' lights.
  * <p>
  * In addition to a position and a direction, spot lights also have a range which 
  * can be used to attenuate the influence of the light depending on the 
- * distance between the light and the effected object.
+ * distance between the light and the affected object.
  * Also the angle of the cone can be tweaked by changing the spot inner angle and the spot outer angle.
- * the spot inner angle determine the cone of light where light has full influence.
- * the spot outer angle determine the cone global cone of light of the spot light.
- * the light intensity slowly decrease between the inner cone and the outer cone.
+ * the spot inner angle determines the cone of light where light has full influence.
+ * the spot outer angle determines the cone global cone of light of the spot light.
+ * the light intensity slowly decreases between the inner cone and the outer cone.
  *  @author Nehon
  */
 public class SpotLight extends Light {
 
     protected Vector3f position = new Vector3f();
-    protected Vector3f direction = new Vector3f(0,-1,0);
+    protected Vector3f direction = new Vector3f(0, -1, 0);
     protected float spotInnerAngle = FastMath.QUARTER_PI / 8;
     protected float spotOuterAngle = FastMath.QUARTER_PI / 6;
     protected float spotRange = 100;
@@ -69,16 +69,9 @@ public class SpotLight extends Light {
     
     protected float outerAngleCosSqr, outerAngleSinSqr;
     protected float outerAngleSinRcp, outerAngleSin, outerAngleCos;
-
+    
     /**
-     * Default constructor for SpotLight.
-     * <p>
-     *     <ul>
-     *         <li>Position will be defaulted to 0,0,0</li>
-     *         <li>Direction will be defaulted to -1 on the Y axis</li>
-     *         <li>Range will be defaulted to 100</li>
-     *     </ul>
-     * </p>
+     * Creates a SpotLight.
      */
     public SpotLight() {
         super();
@@ -86,26 +79,86 @@ public class SpotLight extends Light {
     }
 
     /**
-     * Constructor which allows setting color, position, direction, inner angle, outer angle and range.
-     *
-     * @param color the color of the spotlight.
-     * @param position the position of the spotlight.
-     * @param direction the direction of the spotlight.
-     * @param spotInnerAngle the inner angle of the spotlight.
-     * @param spotOuterAngle the outer angle of the spotlight.
-     * @param spotRange the range of the spotlight.
+     * Creates a SpotLight at the given position and with the given direction.
+     * @param position the position in world space.
+     * @param direction the direction of the light.
+     */
+    public SpotLight(Vector3f position, Vector3f direction) {
+        this();
+        setPosition(position);
+        setDirection(direction);
+    }
+    
+    /**
+     * Creates a SpotLight at the given position, with the given direction, and the
+     * given range.
+     * @param position the position in world space.
+     * @param direction the direction of the light.
+     * @param range the spot light range
      */
-    public SpotLight(final ColorRGBA color, final Vector3f position, final Vector3f direction, final float spotInnerAngle,
-                     final float spotOuterAngle, final float spotRange)
-    {
+    public SpotLight(Vector3f position, Vector3f direction, float range) {
+        this();
+        setPosition(position);
+        setDirection(direction);
+        this.spotRange = range;
+    }
+
+    /**
+     * Creates a SpotLight at the given position, with the given direction and
+     * the given color.
+     * @param position the position in world space.
+     * @param direction the direction of the light.
+     * @param color the light's color.
+     */
+    public SpotLight(Vector3f position, Vector3f direction, ColorRGBA color) {
         super(color);
-        this.position = position;
-        this.direction = direction;
-        this.spotInnerAngle = spotInnerAngle;
-        this.spotOuterAngle = spotOuterAngle;
-        this.spotRange = spotRange;
         computeAngleParameters();
+        setPosition(position);
+        setDirection(direction);
     }
+    
+    
+    /**
+     * Creates a SpotLight at the given position, with the given direction,
+     * the given range and the given color.
+     * @param position the position in world space.
+     * @param direction the direction of the light.
+     * @param range the spot light range
+     * @param color the light's color.
+     */
+    public SpotLight(Vector3f position, Vector3f direction, float range, ColorRGBA color) {
+        super(color);
+        computeAngleParameters();
+        setPosition(position);
+        setDirection(direction);
+        this.spotRange = range;
+    }
+    
+    /**
+     * Creates a SpotLight at the given position, with the given direction,
+     * the given color and the given inner and outer angles 
+     * (controls the falloff of the light)
+     * 
+     * @param position the position in world space.
+     * @param direction the direction of the light.
+     * @param range the spot light range
+     * @param color the light's color.
+     * @param innerAngle the inner angle of the spot light.
+     * @param outerAngle the outer angle of the spot light.
+     * 
+     * @see SpotLight#setSpotInnerAngle(float) 
+     * @see SpotLight#setSpotOuterAngle(float) 
+     */
+    public SpotLight(Vector3f position, Vector3f direction, float range, ColorRGBA color, float innerAngle, float outerAngle) {
+        super(color);
+        this.spotInnerAngle = innerAngle;
+        this.spotOuterAngle = outerAngle;
+        computeAngleParameters();
+        setPosition(position);
+        setDirection(direction);
+        this.spotRange = range;
+    }  
+    
 
     private void computeAngleParameters() {
         float innerCos = FastMath.cos(spotInnerAngle);
@@ -222,7 +275,7 @@ public class SpotLight extends Light {
         return direction;
     }
 
-    public void setDirection(Vector3f direction) {
+    public final void setDirection(Vector3f direction) {
         this.direction.set(direction);
     }
 
@@ -230,7 +283,7 @@ public class SpotLight extends Light {
         return position;
     }
 
-    public void setPosition(Vector3f position) {
+    public final void setPosition(Vector3f position) {
         this.position.set(position);
     }
 

+ 1 - 0
jme3-examples/build.gradle

@@ -21,6 +21,7 @@ dependencies {
 //    compile project(':jme3-bullet-native')
     compile project(':jme3-jbullet')
     compile project(':jme3-jogg')
+    compile project(':jme3-jogl')
     compile project(':jme3-lwjgl')
     compile project(':jme3-networking')
     compile project(':jme3-niftygui')

+ 594 - 0
jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java

@@ -0,0 +1,594 @@
+package com.jme3.renderer.jogl;
+
+import com.jme3.renderer.RendererException;
+import com.jme3.renderer.opengl.GL;
+import com.jme3.renderer.opengl.GL2;
+import com.jme3.renderer.opengl.GL3;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+
+import com.jme3.renderer.opengl.GL4;
+import com.jogamp.opengl.GLContext;
+
+public class JoglGL implements GL, GL2, GL3, GL4 {
+    
+	private static int getLimitBytes(ByteBuffer buffer) {
+        checkLimit(buffer);
+        return buffer.limit();
+    }
+
+    private static int getLimitBytes(ShortBuffer buffer) {
+        checkLimit(buffer);
+        return buffer.limit() * 2;
+    }
+
+    private static int getLimitBytes(FloatBuffer buffer) {
+        checkLimit(buffer);
+        return buffer.limit() * 4;
+    }
+
+    private static int getLimitCount(Buffer buffer, int elementSize) {
+        checkLimit(buffer);
+        return buffer.limit() / elementSize;
+    }
+	
+    private static void checkLimit(Buffer buffer) {
+        if (buffer == null) {
+            return;
+        }
+        if (buffer.limit() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
+        }
+        if (buffer.remaining() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
+        }
+    }
+    
+    @Override
+	public void resetStats() {
+    }
+    
+    @Override
+	public void glActiveTexture(int param1) {
+        GLContext.getCurrentGL().glActiveTexture(param1);
+    }
+
+    @Override
+	public void glAlphaFunc(int param1, float param2) {
+        GLContext.getCurrentGL().getGL2ES1().glAlphaFunc(param1, param2);
+    }
+
+    @Override
+	public void glAttachShader(int param1, int param2) {
+        GLContext.getCurrentGL().getGL2ES2().glAttachShader(param1, param2);
+    }
+
+    @Override
+	public void glBindBuffer(int param1, int param2) {
+        GLContext.getCurrentGL().glBindBuffer(param1, param2);
+    }
+
+    @Override
+	public void glBindTexture(int param1, int param2) {
+        GLContext.getCurrentGL().glBindTexture(param1, param2);
+    }
+
+    @Override
+	public void glBlendFunc(int param1, int param2) {
+        GLContext.getCurrentGL().glBlendFunc(param1, param2);
+    }
+
+    @Override
+	public void glBufferData(int param1, long param2, int param3) {
+        GLContext.getCurrentGL().glBufferData(param1, param2, null, param3);
+    }
+    
+    @Override
+	public void glBufferData(int param1, FloatBuffer param2, int param3) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().glBufferData(param1, getLimitBytes(param2), param2, param3);
+    }
+
+    @Override
+	public void glBufferData(int param1, ShortBuffer param2, int param3) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().glBufferData(param1, getLimitBytes(param2), param2, param3);
+    }
+
+    @Override
+	public void glBufferData(int param1, ByteBuffer param2, int param3) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().glBufferData(param1, getLimitBytes(param2), param2, param3);
+    }
+
+    @Override
+	public void glBufferSubData(int param1, long param2, FloatBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().glBufferSubData(param1, param2, getLimitBytes(param3), param3);
+    }
+
+    @Override
+	public void glBufferSubData(int param1, long param2, ShortBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().glBufferSubData(param1, param2, getLimitBytes(param3), param3);
+    }
+
+    @Override
+	public void glBufferSubData(int param1, long param2, ByteBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().glBufferSubData(param1, param2, getLimitBytes(param3), param3);
+    }
+
+    @Override
+	public void glClear(int param1) {
+        GLContext.getCurrentGL().glClear(param1);
+    }
+
+    @Override
+	public void glClearColor(float param1, float param2, float param3, float param4) {
+        GLContext.getCurrentGL().glClearColor(param1, param2, param3, param4);
+    }
+
+    @Override
+	public void glColorMask(boolean param1, boolean param2, boolean param3, boolean param4) {
+        GLContext.getCurrentGL().glColorMask(param1, param2, param3, param4);
+    }
+
+    @Override
+	public void glCompileShader(int param1) {
+        GLContext.getCurrentGL().getGL2ES2().glCompileShader(param1);
+    }
+
+    @Override
+	public void glCompressedTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) {
+        checkLimit(param7);
+        GLContext.getCurrentGL().glCompressedTexImage2D(param1, param2, param3, param4, param5, param6, getLimitBytes(param7), param7);
+    }
+
+    @Override
+	public void glCompressedTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) {
+        checkLimit(param8);
+        GLContext.getCurrentGL().getGL2ES2().glCompressedTexImage3D(param1, param2, param3, param4, param5, param6, param7, getLimitBytes(param8), param8);
+    }
+
+    @Override
+	public void glCompressedTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) {
+        checkLimit(param8);
+        GLContext.getCurrentGL().glCompressedTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, getLimitBytes(param8), param8);
+    }
+
+    @Override
+	public void glCompressedTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) {
+        checkLimit(param10);
+        GLContext.getCurrentGL().getGL2ES2().glCompressedTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, getLimitBytes(param10), param10);
+    }
+
+    @Override
+	public int glCreateProgram() {
+        return GLContext.getCurrentGL().getGL2ES2().glCreateProgram();
+    }
+
+    @Override
+	public int glCreateShader(int param1) {
+        return GLContext.getCurrentGL().getGL2ES2().glCreateShader(param1);
+    }
+
+    @Override
+	public void glCullFace(int param1) {
+        GLContext.getCurrentGL().glCullFace(param1);
+    }
+
+    @Override
+	public void glDeleteBuffers(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glDeleteBuffers(param1.limit(), param1);
+    }
+
+    @Override
+	public void glDeleteProgram(int param1) {
+        GLContext.getCurrentGL().getGL2ES2().glDeleteProgram(param1);
+    }
+
+    @Override
+	public void glDeleteShader(int param1) {
+        GLContext.getCurrentGL().getGL2ES2().glDeleteShader(param1);
+    }
+
+    @Override
+	public void glDeleteTextures(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glDeleteTextures(param1.limit() ,param1);
+    }
+
+    @Override
+	public void glDepthFunc(int param1) {
+        GLContext.getCurrentGL().glDepthFunc(param1);
+    }
+
+    @Override
+	public void glDepthMask(boolean param1) {
+        GLContext.getCurrentGL().glDepthMask(param1);
+    }
+
+    @Override
+	public void glDepthRange(double param1, double param2) {
+        GLContext.getCurrentGL().glDepthRange(param1, param2);
+    }
+
+    @Override
+	public void glDetachShader(int param1, int param2) {
+        GLContext.getCurrentGL().getGL2ES2().glDetachShader(param1, param2);
+    }
+
+    @Override
+	public void glDisable(int param1) {
+        GLContext.getCurrentGL().glDisable(param1);
+    }
+
+    @Override
+	public void glDisableVertexAttribArray(int param1) {
+        GLContext.getCurrentGL().getGL2ES2().glDisableVertexAttribArray(param1);
+    }
+
+    @Override
+	public void glDrawArrays(int param1, int param2, int param3) {
+        GLContext.getCurrentGL().glDrawArrays(param1, param2, param3);
+    }
+
+    @Override
+	public void glDrawBuffer(int param1) {
+        GLContext.getCurrentGL().getGL2GL3().glDrawBuffer(param1);
+    }
+    
+    @Override
+	public void glDrawRangeElements(int param1, int param2, int param3, int param4, int param5, long param6) {
+        GLContext.getCurrentGL().getGL2ES3().glDrawRangeElements(param1, param2, param3, param4, param5, param6);
+    }
+
+    @Override
+	public void glEnable(int param1) {
+        GLContext.getCurrentGL().glEnable(param1);
+    }
+
+    @Override
+	public void glEnableVertexAttribArray(int param1) {
+        GLContext.getCurrentGL().getGL2ES2().glEnableVertexAttribArray(param1);
+    }
+
+    @Override
+	public void glGenBuffers(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glGenBuffers(param1.limit(), param1);
+    }
+
+    @Override
+	public void glGenTextures(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glGenTextures(param1.limit(), param1);
+    }
+
+    @Override
+	public void glGetBoolean(int param1, ByteBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().glGetBooleanv(param1, param2);
+    }
+    
+    @Override
+	public void glGetBufferSubData(int target, long offset, ByteBuffer data) {
+        checkLimit(data);
+        GLContext.getCurrentGL().getGL2GL3().glGetBufferSubData(target, offset, getLimitBytes(data), data);
+    }
+
+    @Override
+	public int glGetError() {
+        return GLContext.getCurrentGL().glGetError();
+    }
+    
+    @Override
+	public void glGetInteger(int param1, IntBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().glGetIntegerv(param1, param2);
+    }
+
+    @Override
+	public void glGetProgram(int param1, int param2, IntBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().getGL2ES2().glGetProgramiv(param1, param2, param3);
+    }
+
+    @Override
+	public void glGetShader(int param1, int param2, IntBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().getGL2ES2().glGetShaderiv(param1, param2, param3);
+    }
+
+    @Override
+	public String glGetString(int param1) {
+        return GLContext.getCurrentGL().glGetString(param1);
+    }
+    
+    @Override
+	public String glGetString(int param1, int param2) {
+        return GLContext.getCurrentGL().getGL2ES3().glGetStringi(param1, param2);
+    }
+
+    @Override
+	public boolean glIsEnabled(int param1) {
+        return GLContext.getCurrentGL().glIsEnabled(param1);
+    }
+
+    @Override
+	public void glLineWidth(float param1) {
+        GLContext.getCurrentGL().glLineWidth(param1);
+    }
+
+    @Override
+	public void glLinkProgram(int param1) {
+        GLContext.getCurrentGL().getGL2ES2().glLinkProgram(param1);
+    }
+
+    @Override
+	public void glPixelStorei(int param1, int param2) {
+        GLContext.getCurrentGL().glPixelStorei(param1, param2);
+    }
+
+    @Override
+	public void glPointSize(float param1) {
+        GLContext.getCurrentGL().getGL2ES1().glPointSize(param1);
+    }
+
+    @Override
+	public void glPolygonMode(int param1, int param2) {
+        GLContext.getCurrentGL().getGL2().glPolygonMode(param1, param2);
+    }
+
+    @Override
+	public void glPolygonOffset(float param1, float param2) {
+        GLContext.getCurrentGL().glPolygonOffset(param1, param2);
+    }
+
+    @Override
+	public void glReadBuffer(int param1) {
+        GLContext.getCurrentGL().getGL2ES3().glReadBuffer(param1);
+    }
+
+    @Override
+	public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) {
+        checkLimit(param7);
+        GLContext.getCurrentGL().glReadPixels(param1, param2, param3, param4, param5, param6, param7);
+    }
+    
+    @Override
+	public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, long param7) {
+        GLContext.getCurrentGL().glReadPixels(param1, param2, param3, param4, param5, param6, param7);
+    }
+
+    @Override
+	public void glScissor(int param1, int param2, int param3, int param4) {
+        GLContext.getCurrentGL().glScissor(param1, param2, param3, param4);
+    }
+
+    @Override
+	public void glStencilFuncSeparate(int param1, int param2, int param3, int param4) {
+        GLContext.getCurrentGL().getGL2ES2().glStencilFuncSeparate(param1, param2, param3, param4);
+    }
+
+    @Override
+	public void glStencilOpSeparate(int param1, int param2, int param3, int param4) {
+        GLContext.getCurrentGL().getGL2ES2().glStencilOpSeparate(param1, param2, param3, param4);
+    }
+
+    @Override
+	public void glTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) {
+        checkLimit(param9);
+        GLContext.getCurrentGL().glTexImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9);
+    }
+
+    @Override
+	public void glTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) {
+        checkLimit(param10);
+        GLContext.getCurrentGL().getGL2ES2().glTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
+    }
+
+    @Override
+	public void glTexParameterf(int param1, int param2, float param3) {
+        GLContext.getCurrentGL().glTexParameterf(param1, param2, param3);
+    }
+
+    @Override
+	public void glTexParameteri(int param1, int param2, int param3) {
+        GLContext.getCurrentGL().glTexParameteri(param1, param2, param3);
+    }
+
+    @Override
+	public void glTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) {
+        checkLimit(param9);
+        GLContext.getCurrentGL().glTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9);
+    }
+
+    @Override
+	public void glTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10, ByteBuffer param11) {
+        checkLimit(param11);
+        GLContext.getCurrentGL().getGL2ES2().glTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11);
+    }
+
+    @Override
+	public void glUniform1(int param1, FloatBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform1fv(param1, getLimitCount(param2, 1), param2);
+    }
+
+    @Override
+	public void glUniform1(int param1, IntBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform1iv(param1, getLimitCount(param2, 1), param2);
+    }
+
+    @Override
+	public void glUniform1f(int param1, float param2) {
+        GLContext.getCurrentGL().getGL2ES2().glUniform1f(param1, param2);
+    }
+
+    @Override
+	public void glUniform1i(int param1, int param2) {
+        GLContext.getCurrentGL().getGL2ES2().glUniform1i(param1, param2);
+    }
+
+    @Override
+	public void glUniform2(int param1, IntBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform2iv(param1, getLimitCount(param2, 2), param2);
+    }
+
+    @Override
+	public void glUniform2(int param1, FloatBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform2fv(param1, getLimitCount(param2, 2), param2);
+    }
+
+    @Override
+	public void glUniform2f(int param1, float param2, float param3) {
+        GLContext.getCurrentGL().getGL2ES2().glUniform2f(param1, param2, param3);
+    }
+
+    @Override
+	public void glUniform3(int param1, IntBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform3iv(param1, getLimitCount(param2, 3), param2);
+    }
+
+    @Override
+	public void glUniform3(int param1, FloatBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform3fv(param1, getLimitCount(param2, 3), param2);
+    }
+
+    @Override
+	public void glUniform3f(int param1, float param2, float param3, float param4) {
+        GLContext.getCurrentGL().getGL2ES2().glUniform3f(param1, param2, param3, param4);
+    }
+
+    @Override
+	public void glUniform4(int param1, FloatBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform4fv(param1, getLimitCount(param2, 4), param2);
+    }
+
+    @Override
+	public void glUniform4(int param1, IntBuffer param2) {
+        checkLimit(param2);
+        GLContext.getCurrentGL().getGL2ES2().glUniform4iv(param1, getLimitCount(param2, 4), param2);
+    }
+
+    @Override
+	public void glUniform4f(int param1, float param2, float param3, float param4, float param5) {
+        GLContext.getCurrentGL().getGL2ES2().glUniform4f(param1, param2, param3, param4, param5);
+    }
+
+    @Override
+	public void glUniformMatrix3(int param1, boolean param2, FloatBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().getGL2ES2().glUniformMatrix3fv(param1, getLimitCount(param3, 3 * 3), param2, param3);
+    }
+
+    @Override
+	public void glUniformMatrix4(int param1, boolean param2, FloatBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().getGL2ES2().glUniformMatrix4fv(param1, getLimitCount(param3, 4 * 4), param2, param3);
+    }
+
+    @Override
+	public void glUseProgram(int param1) {
+        GLContext.getCurrentGL().getGL2ES2().glUseProgram(param1);
+    }
+
+    @Override
+	public void glVertexAttribPointer(int param1, int param2, int param3, boolean param4, int param5, long param6) {
+        GLContext.getCurrentGL().getGL2ES2().glVertexAttribPointer(param1, param2, param3, param4, param5, param6);
+    }
+
+    @Override
+	public void glViewport(int param1, int param2, int param3, int param4) {
+        GLContext.getCurrentGL().glViewport(param1, param2, param3, param4);
+    }
+
+    @Override
+	public int glGetAttribLocation(int param1, String param2) {
+        // FIXME: Does JOGL require null-terminated strings?????
+        return GLContext.getCurrentGL().getGL2ES2().glGetAttribLocation(param1, param2 + "\0");
+    }
+
+    @Override
+	public int glGetUniformLocation(int param1, String param2) {
+        // FIXME: Does JOGL require null-terminated strings????????
+        return GLContext.getCurrentGL().getGL2ES2().glGetUniformLocation(param1, param2 + "\0");
+    }
+
+    @Override
+	public void glShaderSource(int param1, String[] param2, IntBuffer param3) {
+        checkLimit(param3);
+        GLContext.getCurrentGL().getGL2ES2().glShaderSource(param1, param2.length, param2, param3);
+    }
+
+    @Override
+	public String glGetProgramInfoLog(int program, int maxSize) {
+    	ByteBuffer buffer = ByteBuffer.allocateDirect(maxSize);
+		buffer.order(ByteOrder.nativeOrder());
+		ByteBuffer tmp = ByteBuffer.allocateDirect(4);
+		tmp.order(ByteOrder.nativeOrder());
+		IntBuffer intBuffer = tmp.asIntBuffer();
+
+		GLContext.getCurrentGL().getGL2ES2().glGetProgramInfoLog(program, maxSize, intBuffer, buffer);
+		int numBytes = intBuffer.get(0);
+		byte[] bytes = new byte[numBytes];
+		buffer.get(bytes);
+		return new String(bytes);
+    }
+
+    @Override
+	public String glGetShaderInfoLog(int shader, int maxSize) {
+    	ByteBuffer buffer = ByteBuffer.allocateDirect(maxSize);
+		buffer.order(ByteOrder.nativeOrder());
+		ByteBuffer tmp = ByteBuffer.allocateDirect(4);
+		tmp.order(ByteOrder.nativeOrder());
+		IntBuffer intBuffer = tmp.asIntBuffer();
+
+		GLContext.getCurrentGL().getGL2ES2().glGetShaderInfoLog(shader, maxSize, intBuffer, buffer);
+		int numBytes = intBuffer.get(0);
+		byte[] bytes = new byte[numBytes];
+		buffer.get(bytes);
+		return new String(bytes);
+    }
+
+    @Override
+	public void glBindFragDataLocation(int param1, int param2, String param3) {
+        GLContext.getCurrentGL().getGL2GL3().glBindFragDataLocation(param1, param2, param3);
+    }
+
+    @Override
+	public void glBindVertexArray(int param1) {
+        GLContext.getCurrentGL().getGL2ES3().glBindVertexArray(param1);
+    }
+
+    @Override
+	public void glGenVertexArrays(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().getGL2ES3().glGenVertexArrays(param1.limit(), param1);
+    }
+
+    @Override
+	public void glPatchParameter(int count) {
+        GLContext.getCurrentGL().getGL3().glPatchParameteri(com.jogamp.opengl.GL3.GL_PATCH_VERTICES, count);
+    }
+    
+    @Override
+	public void glDeleteVertexArrays(IntBuffer arrays) {
+        checkLimit(arrays);
+        GLContext.getCurrentGL().getGL2ES3().glDeleteVertexArrays(arrays.limit(), arrays);
+    }
+}

+ 88 - 0
jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLExt.java

@@ -0,0 +1,88 @@
+package com.jme3.renderer.jogl;
+
+import com.jme3.renderer.RendererException;
+import com.jme3.renderer.opengl.GLExt;
+import com.jogamp.opengl.GLContext;
+
+import java.nio.Buffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+public class JoglGLExt implements GLExt {
+
+	private static int getLimitBytes(IntBuffer buffer) {
+        checkLimit(buffer);
+        return buffer.limit() * 4;
+    }
+	
+    private static void checkLimit(Buffer buffer) {
+        if (buffer == null) {
+            return;
+        }
+        if (buffer.limit() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
+        }
+        if (buffer.remaining() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
+        }
+    }
+
+    @Override
+    public void glBufferData(int target, IntBuffer data, int usage) {
+        checkLimit(data);
+        GLContext.getCurrentGL().glBufferData(target, getLimitBytes(data), data, usage);
+    }
+
+    @Override
+    public void glBufferSubData(int target, long offset, IntBuffer data) {
+        checkLimit(data);
+        GLContext.getCurrentGL().glBufferSubData(target, getLimitBytes(data), offset, data);
+    }
+
+    @Override
+    public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) {
+        GLContext.getCurrentGL().getGL2ES3().glDrawArraysInstanced(mode, first, count, primcount);
+    }
+
+    @Override
+    public void glDrawBuffers(IntBuffer bufs) {
+        checkLimit(bufs);
+        GLContext.getCurrentGL().getGL2ES2().glDrawBuffers(bufs.limit(), bufs);
+    }
+
+    @Override
+    public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) {
+        GLContext.getCurrentGL().getGL2ES3().glDrawElementsInstanced(mode, indices_count, type, indices_buffer_offset, primcount);
+    }
+
+    @Override
+    public void glGetMultisample(int pname, int index, FloatBuffer val) {
+        checkLimit(val);
+        GLContext.getCurrentGL().getGL2ES2().glGetMultisamplefv(pname, index, val);
+    }
+
+    @Override
+    public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) {
+        GLContext.getCurrentGL().getGL2ES2().glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);
+    }
+
+    @Override
+    public void glVertexAttribDivisorARB(int index, int divisor) {
+        GLContext.getCurrentGL().getGL2ES3().glVertexAttribDivisor(index, divisor);
+    }
+
+    @Override
+    public Object glFenceSync(int condition, int flags) {
+        return GLContext.getCurrentGL().getGL3ES3().glFenceSync(condition, flags);
+    }
+    
+    @Override
+    public int glClientWaitSync(Object sync, int flags, long timeout) {
+        return GLContext.getCurrentGL().getGL3ES3().glClientWaitSync(((Long) sync).longValue(), flags, timeout);
+    }
+
+    @Override
+    public void glDeleteSync(Object sync) {
+        GLContext.getCurrentGL().getGL3ES3().glDeleteSync(((Long) sync).longValue());
+    }
+}

+ 97 - 0
jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGLFbo.java

@@ -0,0 +1,97 @@
+package com.jme3.renderer.jogl;
+
+import com.jme3.renderer.RendererException;
+import com.jme3.renderer.opengl.GLFbo;
+import com.jogamp.opengl.GLContext;
+
+import java.nio.Buffer;
+import java.nio.IntBuffer;
+
+/**
+ * Implements GLFbo
+ * 
+ * @author Kirill Vainer
+ */
+public class JoglGLFbo implements GLFbo {
+
+    private static void checkLimit(Buffer buffer) {
+        if (buffer == null) {
+            return;
+        }
+        if (buffer.limit() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
+        }
+        if (buffer.remaining() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
+        }
+    }
+    
+    @Override
+    public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
+        GLContext.getCurrentGL().getGL2ES3().glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+    }
+    
+    @Override
+    public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
+        GLContext.getCurrentGL().glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
+    }
+    
+    @Override
+    public void glBindFramebufferEXT(int param1, int param2) {
+        GLContext.getCurrentGL().glBindFramebuffer(param1, param2);
+    }
+    
+    @Override
+    public void glBindRenderbufferEXT(int param1, int param2) {
+        GLContext.getCurrentGL().glBindRenderbuffer(param1, param2);
+    }
+    
+    @Override
+    public int glCheckFramebufferStatusEXT(int param1) {
+        return GLContext.getCurrentGL().glCheckFramebufferStatus(param1);
+    }
+    
+    @Override
+    public void glDeleteFramebuffersEXT(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glDeleteFramebuffers(param1.limit(), param1);
+    }
+    
+    @Override
+    public void glDeleteRenderbuffersEXT(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glDeleteRenderbuffers(param1.limit(), param1);
+    }
+    
+    @Override
+    public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
+        GLContext.getCurrentGL().glFramebufferRenderbuffer(param1, param2, param3, param4);
+    }
+    
+    @Override
+    public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
+        GLContext.getCurrentGL().glFramebufferTexture2D(param1, param2, param3, param4, param5);
+    }
+    
+    @Override
+    public void glGenFramebuffersEXT(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glGenFramebuffers(param1.limit(), param1);
+    }
+    
+    @Override
+    public void glGenRenderbuffersEXT(IntBuffer param1) {
+        checkLimit(param1);
+        GLContext.getCurrentGL().glGenRenderbuffers(param1.limit(), param1);
+    }
+    
+    @Override
+    public void glGenerateMipmapEXT(int param1) {
+        GLContext.getCurrentGL().glGenerateMipmap(param1);
+    }
+    
+    @Override
+    public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
+        GLContext.getCurrentGL().glRenderbufferStorage(param1, param2, param3, param4);
+    }
+}

+ 4 - 55
jme3-jogl/src/main/java/com/jme3/system/jogl/JoglAbstractDisplay.java

@@ -37,22 +37,15 @@ import com.jme3.input.MouseInput;
 import com.jme3.input.TouchInput;
 import com.jme3.input.awt.AwtKeyInput;
 import com.jme3.input.awt.AwtMouseInput;
-import com.jme3.renderer.jogl.JoglRenderer;
 import com.jogamp.opengl.util.Animator;
 import com.jogamp.opengl.util.AnimatorBase;
 import com.jogamp.opengl.util.FPSAnimator;
+
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
-import com.jogamp.opengl.DebugGL2;
-import com.jogamp.opengl.DebugGL3;
-import com.jogamp.opengl.DebugGL3bc;
-import com.jogamp.opengl.DebugGL4;
-import com.jogamp.opengl.DebugGL4bc;
-import com.jogamp.opengl.DebugGLES1;
-import com.jogamp.opengl.DebugGLES2;
-import com.jogamp.opengl.GL;
+
 import com.jogamp.opengl.GLAutoDrawable;
 import com.jogamp.opengl.GLCapabilities;
 import com.jogamp.opengl.GLEventListener;
@@ -124,50 +117,9 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent
         canvas.setSize(settings.getWidth(), settings.getHeight());
         canvas.setIgnoreRepaint(true);
         canvas.addGLEventListener(this);
-
-        if (settings.getBoolean("GraphicsDebug")) {
-            canvas.invoke(false, new GLRunnable() {
-                public boolean run(GLAutoDrawable glad) {
-                    GL gl = glad.getGL();
-                    if (gl.isGLES()) {
-                        if (gl.isGLES1()) {
-                            glad.setGL(new DebugGLES1(gl.getGLES1()));
-                        } else {
-                            if (gl.isGLES2()) {
-                                glad.setGL(new DebugGLES2(gl.getGLES2()));
-                            } else {
-                                // TODO ES3
-                            }
-                        }
-                    } else {
-                        if (gl.isGL4bc()) {
-                            glad.setGL(new DebugGL4bc(gl.getGL4bc()));
-                        } else {
-                            if (gl.isGL4()) {
-                                glad.setGL(new DebugGL4(gl.getGL4()));
-                            } else {
-                                if (gl.isGL3bc()) {
-                                    glad.setGL(new DebugGL3bc(gl.getGL3bc()));
-                                } else {
-                                    if (gl.isGL3()) {
-                                        glad.setGL(new DebugGL3(gl.getGL3()));
-                                    } else {
-                                        if (gl.isGL2()) {
-                                            glad.setGL(new DebugGL2(gl.getGL2()));
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    return true;
-                }
-            });
-        }
-        
-        renderer = new JoglRenderer();
         
-        renderer.setMainFrameBufferSrgb(settings.getGammaCorrection());
+        //FIXME not sure it is the best place to do that
+        renderable.set(true);
     }
 
     protected void startGLCanvas() {
@@ -182,9 +134,6 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent
 
         animator.start();
         wasAnimating = true;
-        
-        //FIXME not sure it is the best place to do that
-        renderable.set(true);
     }
 
     protected void onCanvasAdded() {

+ 24 - 9
jme3-jogl/src/main/java/com/jme3/system/jogl/JoglCanvas.java

@@ -41,28 +41,34 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext
 
     private static final Logger logger = Logger.getLogger(JoglCanvas.class.getName());
     private int width, height;
+    private boolean runningFirstTime = true;
 
     public JoglCanvas(){
         super();
         initGLCanvas();
     }
 
-    public Type getType() {
+    @Override
+	public Type getType() {
         return Type.Canvas;
     }
 
-    public void setTitle(String title) {
+    @Override
+	public void setTitle(String title) {
     }
 
-    public void restart() {
+    @Override
+	public void restart() {
     }
 
-    public void create(boolean waitFor){
+    @Override
+	public void create(boolean waitFor){
         if (waitFor)
             waitFor(true);
     }
 
-    public void destroy(boolean waitFor){
+    @Override
+	public void destroy(boolean waitFor){
         if (waitFor)
             waitFor(false);
         if (animator.isAnimating())
@@ -81,13 +87,20 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext
         startGLCanvas();
     }
 
-    public void init(GLAutoDrawable drawable) {
+    @Override
+	public void init(GLAutoDrawable drawable) {
         canvas.requestFocus();
 
         super.internalCreate();
         logger.fine("Display created.");
 
-        renderer.initialize();
+        // At this point, the OpenGL context is active.
+        if (runningFirstTime){
+            // THIS is the part that creates the renderer.
+            // It must always be called, now that we have the pbuffer workaround.
+            initContextFirstTime();
+            runningFirstTime = false;
+        }
         listener.initialize();
     }
 
@@ -97,7 +110,8 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext
         super.startGLCanvas();
     }
 
-    public void display(GLAutoDrawable glad) {
+    @Override
+	public void display(GLAutoDrawable glad) {
         if (!created.get() && renderer != null){
             listener.destroy();
             logger.fine("Canvas destroyed.");
@@ -129,7 +143,8 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext
 
     }
 
-    public Canvas getCanvas() {
+    @Override
+	public Canvas getCanvas() {
         return canvas;
     }
 

+ 103 - 12
jme3-jogl/src/main/java/com/jme3/system/jogl/JoglContext.java

@@ -36,17 +36,33 @@ import com.jme3.input.JoyInput;
 import com.jme3.input.KeyInput;
 import com.jme3.input.MouseInput;
 import com.jme3.renderer.Renderer;
+import com.jme3.renderer.RendererException;
+import com.jme3.renderer.jogl.JoglGL;
+import com.jme3.renderer.jogl.JoglGLExt;
+import com.jme3.renderer.jogl.JoglGLFbo;
 import com.jme3.renderer.jogl.JoglRenderer;
+import com.jme3.renderer.opengl.GL2;
+import com.jme3.renderer.opengl.GL3;
+import com.jme3.renderer.opengl.GL4;
+import com.jme3.renderer.opengl.GLDebugDesktop;
+import com.jme3.renderer.opengl.GLExt;
+import com.jme3.renderer.opengl.GLFbo;
+import com.jme3.renderer.opengl.GLRenderer;
+import com.jme3.renderer.opengl.GLTiming;
+import com.jme3.renderer.opengl.GLTimingState;
+import com.jme3.renderer.opengl.GLTracer;
 import com.jme3.system.AppSettings;
 import com.jme3.system.JmeContext;
 import com.jme3.system.NanoTimer;
 import com.jme3.system.NativeLibraryLoader;
 import com.jme3.system.SystemListener;
 import com.jme3.system.Timer;
+
 import java.nio.IntBuffer;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+
 import com.jogamp.opengl.GL;
 import com.jogamp.opengl.GL2GL3;
 import com.jogamp.opengl.GLContext;
@@ -62,7 +78,7 @@ public abstract class JoglContext implements JmeContext {
     protected final Object createdLock = new Object();
 
     protected AppSettings settings = new AppSettings(true);
-    protected JoglRenderer renderer;
+    protected Renderer renderer;
     protected Timer timer;
     protected SystemListener listener;
 
@@ -77,43 +93,53 @@ public abstract class JoglContext implements JmeContext {
         }
     }
     
-    public void setSystemListener(SystemListener listener){
+    @Override
+	public void setSystemListener(SystemListener listener){
         this.listener = listener;
     }
 
-    public void setSettings(AppSettings settings) {
+    @Override
+	public void setSettings(AppSettings settings) {
         this.settings.copyFrom(settings);
     }
     
-    public boolean isRenderable(){
+    @Override
+	public boolean isRenderable(){
         return renderable.get();
     }
 
-    public AppSettings getSettings() {
+    @Override
+	public AppSettings getSettings() {
         return settings;
     }
 
-    public Renderer getRenderer() {
+    @Override
+	public Renderer getRenderer() {
         return renderer;
     }
 
-    public MouseInput getMouseInput() {
+    @Override
+	public MouseInput getMouseInput() {
         return mouseInput;
     }
 
-    public KeyInput getKeyInput() {
+    @Override
+	public KeyInput getKeyInput() {
         return keyInput;
     }
 
-    public JoyInput getJoyInput() {
+    @Override
+	public JoyInput getJoyInput() {
         return joyInput;
     }
 
-    public Timer getTimer() {
+    @Override
+	public Timer getTimer() {
         return timer;
     }
 
-    public boolean isCreated() {
+    @Override
+	public boolean isCreated() {
         return created.get();
     }
 
@@ -135,13 +161,78 @@ public abstract class JoglContext implements JmeContext {
             }
         }
     }
+    
+    protected void initContextFirstTime(){
+        if (GLContext.getCurrent().getGLVersionNumber().getMajor() < 2) {
+            throw new RendererException("OpenGL 2.0 or higher is " + 
+                                        "required for jMonkeyEngine");
+        }
+        
+        if (settings.getRenderer().equals("JOGL")) {
+        	com.jme3.renderer.opengl.GL gl = new JoglGL();
+        	GLExt glext = new JoglGLExt();
+        	GLFbo glfbo = new JoglGLFbo();
+            
+            if (settings.getBoolean("GraphicsDebug")) {
+                gl    = new GLDebugDesktop(gl, glext, glfbo);
+                glext = (GLExt) gl;
+                glfbo = (GLFbo) gl;
+            }
+            
+            if (settings.getBoolean("GraphicsTiming")) {
+                GLTimingState timingState = new GLTimingState();
+                gl    = (com.jme3.renderer.opengl.GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class);
+                glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class);
+                glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class);
+            }
+                  
+            if (settings.getBoolean("GraphicsTrace")) {
+                gl    = (com.jme3.renderer.opengl.GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
+                glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class);
+                glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
+            }
+            
+            //FIXME uncomment the line below when the unified renderer is ready for the prime time :)
+            //renderer = new GLRenderer(gl, glext, glfbo);
+            renderer = new JoglRenderer();
+            renderer.initialize();
+        } else {
+            throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
+        }
+        
+        if (GLContext.getCurrentGL().isExtensionAvailable("GL_ARB_debug_output") && settings.getBoolean("GraphicsDebug")) {
+        	GLContext.getCurrent().enableGLDebugMessage(true);
+        	GLContext.getCurrent().addGLDebugListener(new JoglGLDebugOutputHandler());
+        }
+        
+        renderer.setMainFrameBufferSrgb(settings.getGammaCorrection());
+        renderer.setLinearizeSrgbImages(settings.getGammaCorrection());
 
-     public void internalCreate() {
+        // Init input
+        if (keyInput != null) {
+            keyInput.initialize();
+        }
+
+        if (mouseInput != null) {
+            mouseInput.initialize();
+        }
+
+        if (joyInput != null) {
+            joyInput.initialize();
+        }
+    }
+
+    public void internalCreate() {
         timer = new NanoTimer();
         synchronized (createdLock){
             created.set(true);
             createdLock.notifyAll();
         }
+        if (renderable.get()){
+            initContextFirstTime();
+        } else {
+            assert getType() == Type.Canvas;
+        }
     }
 
     protected void internalDestroy() {

+ 80 - 0
jme3-jogl/src/main/java/com/jme3/system/jogl/JoglGLDebugOutputHandler.java

@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009-2015 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT OWNER 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.
+ */
+package com.jme3.system.jogl;
+
+import java.util.HashMap;
+
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLDebugListener;
+import com.jogamp.opengl.GLDebugMessage;
+
+class JoglGLDebugOutputHandler implements GLDebugListener {
+
+    private static final HashMap<Integer, String> constMap = new HashMap<Integer, String>();
+    private static final String MESSAGE_FORMAT = 
+            "[JME3] OpenGL debug message\r\n" +
+            "       ID: %d\r\n" +
+            "       Source: %s\r\n" +
+            "       Type: %s\r\n" +
+            "       Severity: %s\r\n" +
+            "       Message: %s";
+    
+    static {
+        constMap.put(GL2ES2.GL_DEBUG_SOURCE_API, "API");
+        constMap.put(GL2ES2.GL_DEBUG_SOURCE_APPLICATION, "APPLICATION");
+        constMap.put(GL2ES2.GL_DEBUG_SOURCE_OTHER, "OTHER");
+        constMap.put(GL2ES2.GL_DEBUG_SOURCE_SHADER_COMPILER, "SHADER_COMPILER");
+        constMap.put(GL2ES2.GL_DEBUG_SOURCE_THIRD_PARTY, "THIRD_PARTY");
+        constMap.put(GL2ES2.GL_DEBUG_SOURCE_WINDOW_SYSTEM, "WINDOW_SYSTEM");
+        
+        constMap.put(GL2ES2.GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, "DEPRECATED_BEHAVIOR");
+        constMap.put(GL2ES2.GL_DEBUG_TYPE_ERROR, "ERROR");
+        constMap.put(GL2ES2.GL_DEBUG_TYPE_OTHER, "OTHER");
+        constMap.put(GL2ES2.GL_DEBUG_TYPE_PERFORMANCE, "PERFORMANCE");
+        constMap.put(GL2ES2.GL_DEBUG_TYPE_PORTABILITY, "PORTABILITY");
+        constMap.put(GL2ES2.GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, "UNDEFINED_BEHAVIOR");
+        
+        constMap.put(GL2ES2.GL_DEBUG_SEVERITY_HIGH, "HIGH");
+        constMap.put(GL2ES2.GL_DEBUG_SEVERITY_MEDIUM, "MEDIUM");
+        constMap.put(GL2ES2.GL_DEBUG_SEVERITY_LOW, "LOW");
+    }
+    
+    @Override
+	public void messageSent(GLDebugMessage event) {
+    	String sourceStr = constMap.get(event.getDbgSource());
+        String typeStr = constMap.get(event.getDbgType());
+        String severityStr = constMap.get(event.getDbgSeverity());
+        
+        System.err.println(String.format(MESSAGE_FORMAT, event.getDbgId(), sourceStr, typeStr, severityStr, event.getDbgMsg()));
+	}
+    
+}

+ 4 - 55
jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtAbstractDisplay.java

@@ -37,21 +37,14 @@ import com.jme3.input.MouseInput;
 import com.jme3.input.TouchInput;
 import com.jme3.input.jogl.NewtKeyInput;
 import com.jme3.input.jogl.NewtMouseInput;
-import com.jme3.renderer.jogl.JoglRenderer;
 import com.jogamp.newt.opengl.GLWindow;
 import com.jogamp.opengl.util.Animator;
 import com.jogamp.opengl.util.AnimatorBase;
 import com.jogamp.opengl.util.FPSAnimator;
+
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Logger;
-import com.jogamp.opengl.DebugGL2;
-import com.jogamp.opengl.DebugGL3;
-import com.jogamp.opengl.DebugGL3bc;
-import com.jogamp.opengl.DebugGL4;
-import com.jogamp.opengl.DebugGL4bc;
-import com.jogamp.opengl.DebugGLES1;
-import com.jogamp.opengl.DebugGLES2;
-import com.jogamp.opengl.GL;
+
 import com.jogamp.opengl.GLAutoDrawable;
 import com.jogamp.opengl.GLCapabilities;
 import com.jogamp.opengl.GLEventListener;
@@ -103,50 +96,9 @@ public abstract class JoglNewtAbstractDisplay extends JoglContext implements GLE
         canvas.requestFocus();
         canvas.setSize(settings.getWidth(), settings.getHeight());
         canvas.addGLEventListener(this);
-
-        if (settings.getBoolean("GraphicsDebug")) {
-            canvas.invoke(false, new GLRunnable() {
-                public boolean run(GLAutoDrawable glad) {
-                    GL gl = glad.getGL();
-                    if (gl.isGLES()) {
-                        if (gl.isGLES1()) {
-                            glad.setGL(new DebugGLES1(gl.getGLES1()));
-                        } else {
-                            if (gl.isGLES2()) {
-                                glad.setGL(new DebugGLES2(gl.getGLES2()));
-                            } else {
-                                // TODO ES3
-                            }
-                        }
-                    } else {
-                        if (gl.isGL4bc()) {
-                            glad.setGL(new DebugGL4bc(gl.getGL4bc()));
-                        } else {
-                            if (gl.isGL4()) {
-                                glad.setGL(new DebugGL4(gl.getGL4()));
-                            } else {
-                                if (gl.isGL3bc()) {
-                                    glad.setGL(new DebugGL3bc(gl.getGL3bc()));
-                                } else {
-                                    if (gl.isGL3()) {
-                                        glad.setGL(new DebugGL3(gl.getGL3()));
-                                    } else {
-                                        if (gl.isGL2()) {
-                                            glad.setGL(new DebugGL2(gl.getGL2()));
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    return true;
-                }
-            });
-        }
-        
-        renderer = new JoglRenderer();
         
-        renderer.setMainFrameBufferSrgb(settings.getGammaCorrection());
+        //FIXME not sure it is the best place to do that
+        renderable.set(true);
     }
 
     protected void startGLCanvas() {
@@ -161,9 +113,6 @@ public abstract class JoglNewtAbstractDisplay extends JoglContext implements GLE
 
         animator.start();
         wasAnimating = true;
-        
-        //FIXME not sure it is the best place to do that
-        renderable.set(true);
     }
 
     protected void onCanvasAdded() {

+ 25 - 9
jme3-jogl/src/main/java/com/jme3/system/jogl/JoglNewtCanvas.java

@@ -41,6 +41,7 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas
     
     private static final Logger logger = Logger.getLogger(JoglNewtCanvas.class.getName());
     private int width, height;
+    private boolean runningFirstTime = true;
     
     private NewtCanvasAWT newtAwtCanvas;
 
@@ -53,7 +54,9 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas
     protected final void initGLCanvas() {
         super.initGLCanvas();
         newtAwtCanvas = new NewtCanvasAWT(canvas) {
-            @Override
+            private static final long serialVersionUID = 1L;
+
+			@Override
             public void addNotify() {
                 super.addNotify();
                 onCanvasAdded();
@@ -67,22 +70,27 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas
         };
     }
 
-    public Type getType() {
+    @Override
+	public Type getType() {
         return Type.Canvas;
     }
 
-    public void setTitle(String title) {
+    @Override
+	public void setTitle(String title) {
     }
 
-    public void restart() {
+    @Override
+	public void restart() {
     }
 
-    public void create(boolean waitFor){
+    @Override
+	public void create(boolean waitFor){
         if (waitFor)
             waitFor(true);
     }
 
-    public void destroy(boolean waitFor){
+    @Override
+	public void destroy(boolean waitFor){
         if (waitFor)
             waitFor(false);
         if (animator.isAnimating())
@@ -101,13 +109,20 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas
         startGLCanvas();
     }
 
-    public void init(GLAutoDrawable drawable) {
+    @Override
+	public void init(GLAutoDrawable drawable) {
         canvas.requestFocus();
 
         super.internalCreate();
         logger.fine("Display created.");
 
-        renderer.initialize();
+        // At this point, the OpenGL context is active.
+        if (runningFirstTime){
+            // THIS is the part that creates the renderer.
+            // It must always be called, now that we have the pbuffer workaround.
+            initContextFirstTime();
+            runningFirstTime = false;
+        }
         listener.initialize();
     }
 
@@ -117,7 +132,8 @@ public class JoglNewtCanvas extends JoglNewtAbstractDisplay implements JmeCanvas
         super.startGLCanvas();
     }
 
-    public void display(GLAutoDrawable glad) {
+    @Override
+	public void display(GLAutoDrawable glad) {
         if (!created.get() && renderer != null){
             listener.destroy();
             logger.fine("Canvas destroyed.");

+ 3 - 3
sdk/build.gradle

@@ -418,7 +418,7 @@ task cleanSdk() <<{
     file("JME3TestsTemplateAndroid/src/jmetest/").deleteDir()
 }
 
-jar.dependsOn(buildSdk)
-clean.dependsOn(cleanSdk);
-
+tasks.remove(uploadArchives)
 
+jar.dependsOn(buildSdk)
+clean.dependsOn(cleanSdk)