Commits

Michael Ludwig committed cf22190

Improve lighting model interface for FFP renderer.
Improve/fix destroyed resource handling in renderers.
Improve capabilities detection and GL profile selection.
Change DestructibleManager to use PhantomReferences.
Move renderer activation into a new interface, and have activation be handled by HardwareAccessLayer so that only the used renderer is reset or activated.

Comments (0)

Files changed (9)

ferox-demos/src/main/java/com/ferox/scene/controller/ffp/SimpleTest.java

 import com.ferox.renderer.Framework;
 import com.ferox.renderer.OnscreenSurface;
 import com.ferox.renderer.OnscreenSurfaceOptions;
+import com.ferox.renderer.Renderer;
 import com.ferox.renderer.geom.Box;
 import com.ferox.renderer.geom.Geometry;
 import com.ferox.renderer.geom.Sphere;
             int polycount = b.getPolygonType().getPolygonCount(b.getIndexCount() - b.getIndexOffset());
 
             Entity e = system.addEntity();
-            e.add(Renderable.class).setGeometry(b);
+            e.add(Renderable.class).setGeometry(b)
+             .setDrawStyle(Renderer.DrawStyle.SOLID, Renderer.DrawStyle.NONE);
             e.add(LambertianDiffuseModel.class).setColor(c);
+            e.add(BlinnPhongSpecularModel.class).setColor(new ColorRGB(1, 1, 1)).setShininess(5);
             e.add(Transform.class).setMatrix(new Matrix4()
                                                      .set(1, 0, 0, Math.random() * BOUNDS - BOUNDS / 2, 0, 1,
                                                           0, Math.random() * BOUNDS - BOUNDS / 2, 0, 0, 1,

ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/JoglContext.java

 import com.ferox.renderer.FrameworkException;
 import com.ferox.renderer.GlslRenderer;
 import com.ferox.renderer.impl.OpenGLContext;
+import com.ferox.renderer.impl.ShaderFixedFunctionEmulator;
 import com.ferox.renderer.impl.SharedState;
 import com.ferox.renderer.impl.resources.BufferImpl;
 import com.ferox.renderer.impl.resources.ShaderImpl;
     private final List<Runnable> cleanupTasks;
 
     private final SharedState sharedState;
-    private final JoglFixedFunctionRenderer fixed;
+    private final FixedFunctionRenderer fixed;
     private final JoglGlslRenderer glsl;
 
     private int fbo;
         sharedState = new SharedState(caps.getMaxFragmentShaderTextures());
 
         JoglRendererDelegate shared = new JoglRendererDelegate(this, sharedState);
+        glsl = new JoglGlslRenderer(this, shared, caps.getMaxVertexAttributes());
         if (caps.getMajorVersion() < 3) {
             fixed = new JoglFixedFunctionRenderer(this, shared);
         } else {
-            throw new UnsupportedOperationException(
-                    "No emulation shader written yet, can't support FFP renderer");
+            fixed = new ShaderFixedFunctionEmulator(glsl);
         }
-        glsl = new JoglGlslRenderer(this, shared, caps.getMaxVertexAttributes());
     }
 
     /**
 
     @Override
     public void release() {
+        // JOGL did something tricky underneath us, so at least release that context, since release()
+        // is meant to guarantee no context is bound
+        GLContext actual = GLContext.getCurrent();
+        if (actual != context) {
+            if (actual != null) {
+                GLContext.getCurrent().release();
+            }
+            return;
+        }
+
         int error;
         try {
             error = context.getGL().glGetError();
 
     @Override
     public void bindArrayVBO(BufferImpl.BufferHandle vbo) {
-        if (vbo.isDestroyed()) {
+        if (vbo != null && vbo.isDestroyed()) {
             vbo = null;
         }
 
 
     @Override
     public void bindElementVBO(BufferImpl.BufferHandle vbo) {
-        if (vbo.isDestroyed()) {
+        if (vbo != null && vbo.isDestroyed()) {
             vbo = null;
         }
 
 
     @Override
     public void bindShader(ShaderImpl.ShaderHandle shader) {
-        if (shader.isDestroyed()) {
+        if (shader != null && shader.isDestroyed()) {
             shader = null;
         }
 
 
     @Override
     public void bindTexture(int textureUnit, TextureImpl.TextureHandle texture) {
-        if (texture.isDestroyed()) {
+        if (texture != null && texture.isDestroyed()) {
             texture = null;
         }
 

ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/JoglFixedFunctionRenderer.java

 
     // state tracking
     private boolean alphaTestEnabled;
+    private boolean twosidedLighting;
 
     private GL2 gl;
 
 
         transferBuffer = BufferUtil.newByteBuffer(DataType.FLOAT, 16).asFloatBuffer();
         alphaTestEnabled = false;
+        twosidedLighting = false;
     }
 
     @Override
 
             // for the lighting model, we use local viewer and separate specular color, smooth shading, and
             // two sided lighting
-            gl.glLightModeli(GL2.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE);
             gl.glLightModeli(GL2.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE);
             gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL, GL2.GL_SEPARATE_SPECULAR_COLOR);
             gl.glShadeModel(GL2.GL_SMOOTH);
     }
 
     @Override
+    public void setDrawStyle(DrawStyle front, DrawStyle back) {
+        super.setDrawStyle(front, back);
+
+        if (back != DrawStyle.NONE && !twosidedLighting) {
+            gl.glLightModeli(GL2.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE);
+            twosidedLighting = true;
+        } else if (back == DrawStyle.NONE && twosidedLighting) {
+            gl.glLightModeli(GL2.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE);
+            twosidedLighting = false;
+        }
+    }
+
+    @Override
     protected void glMatrixMode(MatrixMode mode) {
         switch (mode) {
         case MODELVIEW:

ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/JoglNEWTSurface.java

         window.setDefaultCloseOperation(
                 WindowClosingProtocol.WindowClosingMode.DO_NOTHING_ON_CLOSE); // we manage this ourselves
         window.setTitle("");
+        window.setPosition(options.getX(), options.getY());
         window.setVisible(true);
         window.requestFocus();
 
         JoglContext context = new JoglContext(factory.getCapabilities(), drawable.createContext(realShare));
         drawable.setRealized(true);
 
+        // OpenGL 3.0 deprecated DEPTH_BITS and STENCIL_BITS so just trust that the surface was created
+        stencilBits = options.getStencilBufferBits();
+        depthBits = options.getDepthBufferBits();
+
         // Detect buffer config while the context is current
         context.makeCurrent();
+
         GL gl = context.getGLContext().getGL();
-
         int[] query = new int[1];
-        gl.glGetIntegerv(GL.GL_STENCIL_BITS, query, 0);
-        stencilBits = query[0];
-
-        gl.glGetIntegerv(GL.GL_DEPTH_BITS, query, 0);
-        depthBits = query[0];
-
         gl.glGetIntegerv(GL2GL3.GL_SAMPLES, query, 0);
         int samples = query[0];
         gl.glGetIntegerv(GL2GL3.GL_SAMPLE_BUFFERS, query, 0);

ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/JoglRendererDelegate.java

     // capabilities
     private boolean initialized;
 
-    // state tracking for buffer clearing
-    private final Vector4 clearColor = new Vector4(0f, 0f, 0f, 0f);
-    private double clearDepth = 1;
-    private int clearStencil = 0;
-
-    // state tracking for draw styles
-    private boolean cullEnabled = true;
-    private int frontPolyMode = GL2GL3.GL_FILL;
-    private int backPolyMode = GL2GL3.GL_FILL;
-
     private GL2GL3 gl;
 
     /**
 
         if (cullFace == 0) {
             // to show both sides, must disable culling
-            if (cullEnabled) {
-                cullEnabled = false;
-                glEnable(GL2GL3.GL_CULL_FACE, false);
-            }
+            glEnable(GL2GL3.GL_CULL_FACE, false);
         } else {
-            if (!cullEnabled) {
-                cullEnabled = true;
-                glEnable(GL2GL3.GL_CULL_FACE, true);
-            }
+            glEnable(GL2GL3.GL_CULL_FACE, true);
             gl.glCullFace(cullFace);
         }
 
         if (front != DrawStyle.NONE) {
-            int frontMode = Utils.getGLPolygonMode(front);
-            if (frontPolyMode != frontMode) {
-                frontPolyMode = frontMode;
-                gl.glPolygonMode(GL2GL3.GL_FRONT, frontMode);
-            }
+            gl.glPolygonMode(GL2GL3.GL_FRONT, Utils.getGLPolygonMode(front));
         }
 
         if (back != DrawStyle.NONE) {
-            int backMode = Utils.getGLPolygonMode(back);
-            if (backPolyMode != backMode) {
-                backPolyMode = backMode;
-                gl.glPolygonMode(GL2GL3.GL_BACK, backMode);
-            }
+            gl.glPolygonMode(GL2GL3.GL_BACK, Utils.getGLPolygonMode(back));
         }
     }
 
             throw new IllegalArgumentException("Clear depth must be in [0, 1], not: " + depth);
         }
 
-        if (!this.clearColor.equals(color)) {
-            this.clearColor.set(color);
-            gl.glClearColor((float) color.x, (float) color.y, (float) color.z, (float) color.w);
-        }
-        if (this.clearDepth != depth) {
-            this.clearDepth = depth;
-            gl.glClearDepth(depth);
-        }
-        if (this.clearStencil != stencil) {
-            this.clearStencil = stencil;
-            gl.glClearStencil(stencil);
-        }
+        gl.glClearColor((float) color.x, (float) color.y, (float) color.z, (float) color.w);
+        gl.glClearDepth(depth);
+        gl.glClearStencil(stencil);
 
         int clearBits = 0;
         if (clearColor) {

ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/JoglSurfaceFactory.java

      * Create a new JoglSurfaceFactory.
      */
     public JoglSurfaceFactory() {
-        boolean forceNoPBuffer = Boolean.getBoolean("ferox.disable.pbuffer");
-        boolean forceNoFBO = Boolean.getBoolean("ferox.disable.fbo");
-
-        profile = GLProfile.get(GLProfile.GL2); // FIXME select from 3 as well
+        if (GLProfile.isAvailable(GLProfile.GL4)) {
+            profile = GLProfile.get(GLProfile.GL4);
+        } else if (GLProfile.isAvailable(GLProfile.GL3)) {
+            profile = GLProfile.get(GLProfile.GL3);
+        } else {
+            profile = GLProfile.get(GLProfile.GL2);
+        }
 
         display = NewtFactory.createDisplay(null);
         display.addReference();
         }
 
         defaultMode = convert(device.getOriginalMode());
-        caps = JoglCapabilities
-                .computeCapabilities(profile, convertMap.keySet().toArray(new DisplayMode[convertMap.size()]),
-                                     forceNoPBuffer, forceNoFBO);
+        caps = JoglCapabilities.computeCapabilities(profile, convertMap.keySet().toArray(
+                new DisplayMode[convertMap.size()]));
     }
 
     @Override
     public void destroy() {
         screen.removeReference();
         display.removeReference();
-
-        screen.destroy();
-        display.destroy();
     }
 
     public MonitorDevice getMonitor() {

ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/OnscreenShadowContext.java

 
         GLDrawable drawable = GLDrawableFactory.getFactory(creator.getGLProfile()).createGLDrawable(window);
         GLContext context = drawable.createContext(shareWith == null ? null : shareWith.getGLContext());
+        drawable.setRealized(true);
+
+        // cycle context status
+        context.makeCurrent();
+        context.release();
 
         return new OnscreenShadowContext(creator, window, context);
     }

ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/PbufferShadowContext.java

 
         GLContext realShare = (shareWith == null ? null : shareWith.getGLContext());
         GLCapabilities glCaps = new GLCapabilities(creator.getGLProfile());
-        glCaps.setPBuffer(true);
+        glCaps.setPBuffer(false);
         glCaps.setFBO(false);
         glCaps.setOnscreen(false);
 
                                                            .createOffscreenAutoDrawable(device, glCaps,
                                                                                         new DefaultGLCapabilitiesChooser(),
                                                                                         1, 1, realShare);
+
+        // cycle context status
+        pbuffer.getContext().makeCurrent();
+        pbuffer.getContext().release();
+
         try {
             return new PbufferShadowContext(creator.getCapabilities(), pbuffer);
         } catch (RuntimeException re) {

ferox-renderer-jogl/src/test/java/lwjgl/JoglFixedFunctionTest.java

  */
 public class JoglFixedFunctionTest {
     public static void main(String[] args) throws Exception {
-        final Framework framework = Framework.Factory.create();
+        Framework framework = Framework.Factory.create();
         final OnscreenSurface s = framework.createSurface(new OnscreenSurfaceOptions().windowed(500, 500));
         s.setTitle("Hello World");
         s.setVSyncEnabled(true);
 
         final Geometry box = Box.create(framework, 3.0);
 
-        while (!s.isDestroyed()) {
-            framework.invoke(new Task<Void>() {
-                @Override
-                public Void run(HardwareAccessLayer access) {
-                    Context c = access.setActiveSurface(s);
-                    FixedFunctionRenderer r = c.getFixedFunctionRenderer();
-                    r.clear(true, true, true);
+        try {
+            while (!s.isDestroyed()) {
+                framework.invoke(new Task<Void>() {
+                    @Override
+                    public Void run(HardwareAccessLayer access) {
+                        Context c = access.setActiveSurface(s);
+                        FixedFunctionRenderer r = c.getFixedFunctionRenderer();
+                        r.clear(true, true, true);
 
-                    Frustum view = new Frustum(60.0, 1.0, 1.0, 1000.0);
-                    view.setOrientation(new Vector3(0, 0, 150), new Vector3(0, 0, -1), new Vector3(0, 1, 0));
-                    r.setProjectionMatrix(view.getProjectionMatrix());
-                    r.setModelViewMatrix(view.getViewMatrix());
+                        Frustum view = new Frustum(60.0, 1.0, 1.0, 1000.0);
+                        view.setOrientation(new Vector3(0, 0, 150), new Vector3(0, 0, -1),
+                                            new Vector3(0, 1, 0));
+                        r.setProjectionMatrix(view.getProjectionMatrix());
+                        r.setModelViewMatrix(view.getViewMatrix());
 
-                    r.setLightingEnabled(true);
-                    r.setLightEnabled(0, true);
-                    r.setLightColor(0, new Vector4(.4, .2, 0, 1), new Vector4(.4, .2, 0, 1),
-                                    new Vector4(1, 1, 1, 1));
-                    r.setLightPosition(0, new Vector4(50, 50, 50, 1));
+                        r.setLightingEnabled(true);
+                        r.setLightEnabled(0, true);
+                        r.setLightColor(0, new Vector4(.4, .2, 0, 1), new Vector4(.4, .2, 0, 1),
+                                        new Vector4(1, 1, 1, 1));
+                        r.setLightPosition(0, new Vector4(50, 50, 50, 1));
 
-                    r.setMaterialDiffuse(new Vector4(.8, .8, .8, 1));
+                        r.setMaterialDiffuse(new Vector4(.8, .8, .8, 1));
 
-                    r.setNormals(box.getNormals());
-                    r.setVertices(box.getVertices());
-                    r.setIndices(box.getIndices());
+                        r.setNormals(box.getNormals());
+                        r.setVertices(box.getVertices());
+                        r.setIndices(box.getIndices());
 
 
-                    Matrix4 m = new Matrix4();
-                    Vector4 t = new Vector4();
-                    for (int i = 0; i < 10000; i++) {
-                        t.set(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50,
-                              1);
-                        m.setIdentity().setCol(3, t);
-                        r.setModelViewMatrix(m.mul(view.getViewMatrix(), m));
+                        Matrix4 m = new Matrix4();
+                        Vector4 t = new Vector4();
+                        for (int i = 0; i < 10000; i++) {
+                            t.set(Math.random() * 100 - 50, Math.random() * 100 - 50,
+                                  Math.random() * 100 - 50, 1);
+                            m.setIdentity().setCol(3, t);
+                            r.setModelViewMatrix(m.mul(view.getViewMatrix(), m));
 
-                        r.render(box.getPolygonType(), box.getIndexOffset(), box.getIndexCount());
+                            r.render(box.getPolygonType(), box.getIndexOffset(), box.getIndexCount());
+                        }
+
+                        c.flush();
+
+                        return null;
                     }
-
-                    c.flush();
-
-                    return null;
-                }
-            }).get();
+                }).get();
+            }
+        } finally {
+            framework.destroy();
         }
-        framework.destroy();
     }
 }