Commits

Michael Ludwig committed ecbd3cf

Add delegating debug renderer implementations for renderers, and add static methods to Framework.Factory to set system properties from within java.

  • Participants
  • Parent commits c1e8567

Comments (0)

Files changed (14)

File ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/JoglCapabilities.java

     private boolean queried = false;
 
     public static JoglCapabilities computeCapabilities(GLProfile profile, DisplayMode[] availableModes) {
-        boolean forceNoPBuffer = Boolean.getBoolean("ferox.disable.pbuffer");
-        boolean forceNoFBO = Boolean.getBoolean("ferox.disable.fbo");
+        boolean forceNoPBuffer = Boolean.getBoolean(Framework.Factory.DISABLE_PBUFFER_PROPERTY);
+        boolean forceNoFBO = Boolean.getBoolean(Framework.Factory.DISABLE_FBO_PROPERTY);
 
         if (NativeWindowFactory.getNativeWindowType(true).equals(NativeWindowFactory.TYPE_MACOSX) &&
             profile.isGL3()) {

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

 import com.ferox.renderer.impl.resources.ShaderImpl;
 import com.ferox.renderer.impl.resources.TextureImpl;
 
-import javax.media.opengl.*;
+import javax.media.opengl.GL;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GLContext;
+import javax.media.opengl.GLException;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
     public void makeCurrent() {
         try {
             context.makeCurrent();
-
             if (vao < 0) {
                 // make a vao for attributes
                 int[] id = new int[1];
     @Override
     public String checkGLErrors() {
         int error = context.getGL().glGetError();
-        return (error == 0 ? null : translateGLErrorString(error));
-    }
-
-    private static String translateGLErrorString(int error_code) {
-        switch (error_code) {
-        case GL.GL_NO_ERROR:
-            return "No error";
-        case GL.GL_INVALID_ENUM:
-            return "Invalid enum";
-        case GL.GL_INVALID_VALUE:
-            return "Invalid value";
-        case GL.GL_INVALID_OPERATION:
-            return "Invalid operation";
-        case GL2.GL_STACK_OVERFLOW:
-            return "Stack overflow";
-        case GL2.GL_STACK_UNDERFLOW:
-            return "Stack underflow";
-        case GL.GL_OUT_OF_MEMORY:
-            return "Out of memory";
-        case GL2.GL_TABLE_TOO_LARGE:
-            return "Table too large";
-        case GL3.GL_INVALID_FRAMEBUFFER_OPERATION:
-            return "Invalid framebuffer operation";
-        default:
-            return null;
-        }
+        return Utils.getGLErrorString(error);
     }
 
     @Override

File ferox-renderer-jogl/src/main/java/com/ferox/renderer/impl/jogl/Utils.java

 import com.ferox.renderer.impl.ContextManager;
 import com.ferox.renderer.impl.resources.TextureImpl;
 
-import javax.media.opengl.GL;
-import javax.media.opengl.GL2;
-import javax.media.opengl.GL2ES1;
-import javax.media.opengl.GL2GL3;
+import javax.media.opengl.*;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
  * @author Michael Ludwig
  */
 public class Utils {
+    public static String getGLErrorString(int errorCode) {
+        switch (errorCode) {
+        case GL.GL_NO_ERROR:
+            return null;
+        case GL.GL_INVALID_ENUM:
+            return "invalid enum";
+        case GL.GL_INVALID_VALUE:
+            return "invalid value";
+        case GL.GL_INVALID_OPERATION:
+            return "invalid operation";
+        case GL2.GL_STACK_OVERFLOW:
+            return "stack overflow";
+        case GL2.GL_STACK_UNDERFLOW:
+            return "stack underflow";
+        case GL.GL_OUT_OF_MEMORY:
+            return "out of memory";
+        case GL2.GL_TABLE_TOO_LARGE:
+            return "table too large";
+        case GL3.GL_INVALID_FRAMEBUFFER_OPERATION:
+            return "invalid framebuffer operation";
+        default:
+            return "unknown error code (" + errorCode + ")";
+        }
+    }
+
     /**
      * Return the VariableType enum value associated with the returned GL enum for glsl variable type.
      */

File ferox-renderer-lwjgl/src/main/java/com/ferox/renderer/impl/lwjgl/LwjglCapabilities.java

 
     public static LwjglCapabilities computeCapabilities(ContextAttribs attribs,
                                                         DisplayMode[] availableModes) {
-        boolean forceNoPBuffer = Boolean.getBoolean("ferox.disable.pbuffer");
-        boolean forceNoFBO = Boolean.getBoolean("ferox.disable.fbo");
+        boolean forceNoPBuffer = Boolean.getBoolean(Framework.Factory.DISABLE_PBUFFER_PROPERTY);
+        boolean forceNoFBO = Boolean.getBoolean(Framework.Factory.DISABLE_FBO_PROPERTY);
 
         // Technically on Mac 10.7+ pbuffers are deprecated but LWJGL does not support sharing contexts
         // between AWTGLCanvas and Display. That means there's no real alternative. Also, unlike JOGL

File ferox-renderer-lwjgl/src/main/java/com/ferox/renderer/impl/lwjgl/LwjglContext.java

     @Override
     public String checkGLErrors() {
         int error = GL11.glGetError();
-        return (error == 0 ? null : Util.translateGLErrorString(error));
+        return Utils.getGLErrorString(error);
     }
 
     @Override

File ferox-renderer-lwjgl/src/main/java/com/ferox/renderer/impl/lwjgl/Utils.java

  * @author Michael Ludwig
  */
 public class Utils {
+    public static String getGLErrorString(int errorCode) {
+        switch (errorCode) {
+        case GL11.GL_NO_ERROR:
+            return null;
+        case GL11.GL_INVALID_ENUM:
+            return "invalid enum";
+        case GL11.GL_INVALID_VALUE:
+            return "invalid value";
+        case GL11.GL_INVALID_OPERATION:
+            return "invalid operation";
+        case GL11.GL_STACK_OVERFLOW:
+            return "stack overflow";
+        case GL11.GL_STACK_UNDERFLOW:
+            return "stack underflow";
+        case GL11.GL_OUT_OF_MEMORY:
+            return "out of memory";
+        case ARBImaging.GL_TABLE_TOO_LARGE:
+            return "table too large";
+        case GL30.GL_INVALID_FRAMEBUFFER_OPERATION:
+            return "invalid framebuffer operation";
+        default:
+            return "unknown error code (" + errorCode + ")";
+        }
+    }
+
     /**
      * Return the VariableType enum value associated with the returned GL enum for glsl variable type.
      */

File ferox-renderer/src/main/java/com/ferox/renderer/Framework.java

      * Factory class for Frameworks
      */
     public static final class Factory {
-        private static final String FACTORY_DIR = "META-INF/ferox/renderer/";
+        public static final String FACTORY_DIR = "META-INF/ferox/renderer/";
+
+        /**
+         * System properties that control aspects of how the Framework functions.
+         */
+        public static final String DISABLE_PBUFFER_PROPERTY = "ferox.disable.pbuffer";
+        public static final String DISABLE_FBO_PROPERTY = "ferox.disable.fbo";
+        public static final String DEBUG_PROPERTY = "ferox.debug";
 
         private Factory() {
         }
 
+        /**
+         * Disable pbuffer usage by frameworks created after this method is called. When disabled, the
+         * framework's capabilities will report that pbuffers are not supported at all (regardless of actual
+         * hardware support).
+         *
+         * @see Capabilities#getPBufferSupport()
+         */
+        public static void disablePBuffers() {
+            System.setProperty(DISABLE_PBUFFER_PROPERTY, Boolean.FALSE.toString());
+        }
+
+        /**
+         * Enable pbuffer usage by frameworks created after this method is called. This is ignored if the
+         * hardware does not support pbuffers at all. Pbuffers are enabled by default unless a property
+         * overrides it.
+         *
+         * @see Capabilities#getPBufferSupport()
+         */
+        public static void enablePBuffers() {
+            System.setProperty(DISABLE_PBUFFER_PROPERTY, Boolean.TRUE.toString());
+        }
+
+        /**
+         * Disable framewbuffer object usage by frameworks created after this method is called. When disabled,
+         * the framework's capabilities will report that fbos are not support at all (regardless of actual
+         * hardware support).
+         *
+         * @see Capabilities#getFBOSupport()
+         */
+        public static void disableFBOs() {
+            System.setProperty(DISABLE_FBO_PROPERTY, Boolean.FALSE.toString());
+        }
+
+        /**
+         * Enable framebuffer object by frameworks created after this method is called. This is ignored if the
+         * hardare does not support fbos at all. FBOs are enabled by default unless a property overrides it.
+         *
+         * @see Capabilities#getFBOSupport()
+         */
+        public static void enableFBOs() {
+            System.setProperty(DISABLE_FBO_PROPERTY, Boolean.TRUE.toString());
+        }
+
+        /**
+         * Enable debug mode on renderers returned by activated {@link Context Contexts}. This will affect all
+         * Frameworks created after this is called. When enabled, every call to the renderer will
+         * automatically query OpenGL's error flag and throw an exception if there is an error.
+         * <p/>
+         * The renderer APIs have been designed to make it impossible to produce OpenGL errors and should
+         * throw more specific exceptions before invoking OpenGL commands. However, this can be useful if
+         * there is suspicion about the renderer itself.
+         */
+        public static void enableDebugMode() {
+            System.setProperty(DEBUG_PROPERTY, Boolean.TRUE.toString());
+        }
+
+        /**
+         * Disable debug mode on renderers returned by activated {@link Context Contexts}. This will affect
+         * all Frameworks created after this is called. By default debug mode is disabled unless enabled by a
+         * system property.
+         *
+         * @see #enableDebugMode()
+         */
+        public static void disableDebugMode() {
+            System.setProperty(DEBUG_PROPERTY, Boolean.FALSE.toString());
+        }
+
         public static Framework create() {
             Class<? extends ResourceFactory> resourceFactory = getImplementation(ResourceFactory.class);
             Class<? extends SurfaceFactory> surfaceFactory = getImplementation(SurfaceFactory.class);

File ferox-renderer/src/main/java/com/ferox/renderer/Renderer.java

      * @throws NullPointerException     if function, src, or dst are null
      * @throws IllegalArgumentException if dst is {@link BlendFactor#SRC_ALPHA_SATURATE}
      * @see #setBlendModeAlpha(BlendFunction, BlendFactor, BlendFactor)
-     * @see #setBlendModeRgb(BlendFunction, BlendFactor, BlendFactor)
+     * @see #setBlendModeRGB(BlendFunction, BlendFactor, BlendFactor)
      */
     public void setBlendMode(BlendFunction function, BlendFactor src, BlendFactor dst);
 
      * @throws IllegalArgumentException if dst is {@link BlendFactor#SRC_ALPHA_SATURATE}
      * @see #setBlendModeAlpha(BlendFunction, BlendFactor, BlendFactor)
      */
-    public void setBlendModeRgb(BlendFunction function, BlendFactor src, BlendFactor dst);
+    public void setBlendModeRGB(BlendFunction function, BlendFactor src, BlendFactor dst);
 
     /**
      * <p/>
      *
      * @throws NullPointerException     if function, src, or dst are null
      * @throws IllegalArgumentException if dst is {@link BlendFactor#SRC_ALPHA_SATURATE}
-     * @see #setBlendModeRgb(BlendFunction, BlendFactor, BlendFactor)
+     * @see #setBlendModeRGB(BlendFunction, BlendFactor, BlendFactor)
      */
     public void setBlendModeAlpha(BlendFunction function, BlendFactor src, BlendFactor dst);
 

File ferox-renderer/src/main/java/com/ferox/renderer/impl/AbstractRenderer.java

     }
 
     @Override
-    public void setBlendModeRgb(BlendFunction function, BlendFactor src, BlendFactor dst) {
+    public void setBlendModeRGB(BlendFunction function, BlendFactor src, BlendFactor dst) {
         delegate.setBlendModeRgb(function, src, dst);
     }
 

File ferox-renderer/src/main/java/com/ferox/renderer/impl/DebugFixedFunctionRenderer.java

+package com.ferox.renderer.impl;
+
+import com.ferox.math.Const;
+import com.ferox.math.Matrix4;
+import com.ferox.math.Vector3;
+import com.ferox.math.Vector4;
+import com.ferox.renderer.*;
+
+/**
+ *
+ */
+public class DebugFixedFunctionRenderer implements FixedFunctionRenderer {
+    private final FixedFunctionRenderer renderer;
+    private final OpenGLContext context;
+
+    public DebugFixedFunctionRenderer(OpenGLContext context, FixedFunctionRenderer renderer) {
+        this.context = context;
+        this.renderer = renderer;
+    }
+
+    private void checkGLErrors() {
+        String error = context.checkGLErrors();
+        if (error != null) {
+            throw new FrameworkException("OpenGL error: " + error);
+        }
+    }
+
+    @Override
+    public ContextState<FixedFunctionRenderer> getCurrentState() {
+        return renderer.getCurrentState();
+    }
+
+    @Override
+    public void setCurrentState(ContextState<FixedFunctionRenderer> state) {
+        renderer.setCurrentState(state);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setFogEnabled(boolean enable) {
+        renderer.setFogEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setFogColor(@Const Vector4 color) {
+        renderer.setFogColor(color);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setFogLinear(double start, double end) {
+        renderer.setFogLinear(start, end);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setFogExponential(double density, boolean squared) {
+        renderer.setFogExponential(density, squared);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setAlphaTest(Comparison test, double refValue) {
+        renderer.setAlphaTest(test, refValue);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLightingEnabled(boolean enable) {
+        renderer.setLightingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setGlobalAmbientLight(@Const Vector4 ambient) {
+        renderer.setGlobalAmbientLight(ambient);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLightEnabled(int light, boolean enable) {
+        renderer.setLightEnabled(light, enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLightPosition(int light, @Const Vector4 pos) {
+        renderer.setLightPosition(light, pos);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLightColor(int light, @Const Vector4 amb, @Const Vector4 diff, @Const Vector4 spec) {
+        renderer.setLightColor(light, amb, diff, spec);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setSpotlight(int light, @Const Vector3 dir, double angle, double exponent) {
+        renderer.setSpotlight(light, dir, angle, exponent);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLightAttenuation(int light, double constant, double linear, double quadratic) {
+        renderer.setLightAttenuation(light, constant, linear, quadratic);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setMaterial(@Const Vector4 amb, @Const Vector4 diff, @Const Vector4 spec,
+                            @Const Vector4 emm) {
+        renderer.setMaterial(amb, diff, spec, emm);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setMaterialDiffuse(@Const Vector4 diff) {
+        renderer.setMaterialDiffuse(diff);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setMaterialAmbient(@Const Vector4 amb) {
+        renderer.setMaterialAmbient(amb);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setMaterialSpecular(@Const Vector4 spec) {
+        renderer.setMaterialSpecular(spec);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setMaterialEmissive(@Const Vector4 emm) {
+        renderer.setMaterialEmissive(emm);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setMaterialShininess(double shininess) {
+        renderer.setMaterialShininess(shininess);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTexture(int tex, Sampler image) {
+        renderer.setTexture(tex, image);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureColor(int tex, @Const Vector4 color) {
+        renderer.setTextureColor(tex, color);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureCoordinateSource(int tex, TexCoordSource gen) {
+        renderer.setTextureCoordinateSource(tex, gen);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureObjectPlanes(int tex, @Const Matrix4 planes) {
+        renderer.setTextureObjectPlanes(tex, planes);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureEyePlanes(int tex, @Const Matrix4 planes) {
+        renderer.setTextureEyePlanes(tex, planes);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureTransform(int tex, @Const Matrix4 matrix) {
+        renderer.setTextureTransform(tex, matrix);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureCombineRGB(int tex, CombineFunction function, CombineSource src0,
+                                     CombineOperand op0, CombineSource src1, CombineOperand op1,
+                                     CombineSource src2, CombineOperand op2) {
+        renderer.setTextureCombineRGB(tex, function, src0, op0, src1, op1, src2, op2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureCombineAlpha(int tex, CombineFunction function, CombineSource src0,
+                                       CombineOperand op0, CombineSource src1, CombineOperand op1,
+                                       CombineSource src2, CombineOperand op2) {
+        renderer.setTextureCombineAlpha(tex, function, src0, op0, src1, op1, src2, op2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setProjectionMatrix(@Const Matrix4 projection) {
+        renderer.setProjectionMatrix(projection);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setModelViewMatrix(@Const Matrix4 modelView) {
+        renderer.setModelViewMatrix(modelView);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setVertices(VertexAttribute vertices) {
+        renderer.setVertices(vertices);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setNormals(VertexAttribute normals) {
+        renderer.setNormals(normals);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setColors(VertexAttribute colors) {
+        renderer.setColors(colors);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setTextureCoordinates(int tex, VertexAttribute texCoords) {
+        renderer.setTextureCoordinates(tex, texCoords);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setPointAntiAliasingEnabled(boolean enable) {
+        renderer.setPointAntiAliasingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLineAntiAliasingEnabled(boolean enable) {
+        renderer.setLineAntiAliasingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setPolygonAntiAliasingEnabled(boolean enable) {
+        renderer.setPolygonAntiAliasingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setPointSize(double width) {
+        renderer.setPointSize(width);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLineSize(double width) {
+        renderer.setLineSize(width);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilUpdate(StencilUpdate stencilFail, StencilUpdate depthFail,
+                                 StencilUpdate depthPass) {
+        renderer.setStencilUpdate(stencilFail, depthFail, depthPass);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilUpdateFront(StencilUpdate stencilFail, StencilUpdate depthFail,
+                                      StencilUpdate depthPass) {
+        renderer.setStencilUpdateFront(stencilFail, depthFail, depthPass);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilUpdateBack(StencilUpdate stencilFail, StencilUpdate depthFail,
+                                     StencilUpdate depthPass) {
+        renderer.setStencilUpdateBack(stencilFail, depthFail, depthPass);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTest(Comparison test, int refValue, int testMask) {
+        renderer.setStencilTest(test, refValue, testMask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTestFront(Comparison test, int refValue, int testMask) {
+        renderer.setStencilTestFront(test, refValue, testMask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTestBack(Comparison test, int refValue, int testMask) {
+        renderer.setStencilTestBack(test, refValue, testMask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTestEnabled(boolean enable) {
+        renderer.setStencilTestEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilWriteMask(int mask) {
+        renderer.setStencilWriteMask(mask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilWriteMask(int front, int back) {
+        renderer.setStencilWriteMask(front, back);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthTest(Comparison test) {
+        renderer.setDepthTest(test);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthWriteMask(boolean mask) {
+        renderer.setDepthWriteMask(mask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthOffsets(double factor, double units) {
+        renderer.setDepthOffsets(factor, units);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthOffsetsEnabled(boolean enable) {
+        renderer.setDepthOffsetsEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDrawStyle(DrawStyle style) {
+        renderer.setDrawStyle(style);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDrawStyle(DrawStyle front, DrawStyle back) {
+        renderer.setDrawStyle(front, back);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setColorWriteMask(boolean red, boolean green, boolean blue, boolean alpha) {
+        renderer.setColorWriteMask(red, green, blue, alpha);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendingEnabled(boolean enable) {
+        renderer.setBlendingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendColor(@Const Vector4 color) {
+        renderer.setBlendColor(color);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendMode(BlendFunction function, BlendFactor src, BlendFactor dst) {
+        renderer.setBlendMode(function, src, dst);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendModeRGB(BlendFunction function, BlendFactor src, BlendFactor dst) {
+        renderer.setBlendModeRGB(function, src, dst);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendModeAlpha(BlendFunction function, BlendFactor src, BlendFactor dst) {
+        renderer.setBlendModeAlpha(function, src, dst);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setIndices(ElementBuffer indices) {
+        renderer.setIndices(indices);
+        checkGLErrors();
+    }
+
+    @Override
+    public int render(PolygonType polyType, int offset, int count) {
+        int rendered = renderer.render(polyType, offset, count);
+        checkGLErrors();
+        return rendered;
+    }
+
+    @Override
+    public void reset() {
+        renderer.reset();
+        checkGLErrors();
+    }
+
+    @Override
+    public void clear(boolean clearColor, boolean clearDepth, boolean clearStencil) {
+        renderer.clear(clearColor, clearDepth, clearStencil);
+        checkGLErrors();
+    }
+
+    @Override
+    public void clear(boolean clearColor, boolean clearDepth, boolean clearStencil, @Const Vector4 color,
+                      double depth, int stencil) {
+        renderer.clear(clearColor, clearDepth, clearStencil, color, depth, stencil);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setViewport(int x, int y, int width, int height) {
+        renderer.setViewport(x, y, width, height);
+        checkGLErrors();
+    }
+}

File ferox-renderer/src/main/java/com/ferox/renderer/impl/DebugGlslRenderer.java

+package com.ferox.renderer.impl;
+
+import com.ferox.math.*;
+import com.ferox.renderer.*;
+
+/**
+ *
+ */
+public class DebugGlslRenderer implements GlslRenderer {
+    private final GlslRenderer delegate;
+    private final OpenGLContext context;
+
+    public DebugGlslRenderer(OpenGLContext context, GlslRenderer delegate) {
+        this.delegate = delegate;
+        this.context = context;
+    }
+
+    private void checkGLErrors() {
+        String error = context.checkGLErrors();
+        if (error != null) {
+            throw new FrameworkException("OpenGL error: " + error);
+        }
+    }
+
+    @Override
+    public ContextState<GlslRenderer> getCurrentState() {
+        return delegate.getCurrentState();
+    }
+
+    @Override
+    public void setCurrentState(ContextState<GlslRenderer> state) {
+        delegate.setCurrentState(state);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setShader(Shader shader) {
+        delegate.setShader(shader);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, VertexAttribute attr) {
+        delegate.bindAttribute(var, attr);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, int column, VertexAttribute attr) {
+        delegate.bindAttribute(var, column, attr);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, double val) {
+        delegate.bindAttribute(var, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, double v1, double v2) {
+        delegate.bindAttribute(var, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, @Const Vector3 v) {
+        delegate.bindAttribute(var, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, @Const Vector4 v) {
+        delegate.bindAttribute(var, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, double m00, double m01, double m10, double m11) {
+        delegate.bindAttribute(var, m00, m01, m10, m11);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, @Const Matrix3 v) {
+        delegate.bindAttribute(var, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, @Const Matrix4 v) {
+        delegate.bindAttribute(var, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, int val) {
+        delegate.bindAttribute(var, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, int v1, int v2) {
+        delegate.bindAttribute(var, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, int v1, int v2, int v3) {
+        delegate.bindAttribute(var, v1, v2, v3);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttribute(Shader.Attribute var, int v1, int v2, int v3, int v4) {
+        delegate.bindAttribute(var, v1, v2, v3, v4);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, double val) {
+        delegate.setUniform(var, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, double v1, double v2) {
+        delegate.setUniform(var, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, @Const Vector3 v) {
+        delegate.setUniform(var, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, @Const Vector4 v) {
+        delegate.setUniform(var, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, double m00, double m01, double m10, double m11) {
+        delegate.setUniform(var, m00, m01, m10, m11);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, @Const Matrix3 val) {
+        delegate.setUniform(var, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, @Const Matrix4 val) {
+        delegate.setUniform(var, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, int val) {
+        delegate.setUniform(var, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, int v1, int v2) {
+        delegate.setUniform(var, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, int v1, int v2, int v3) {
+        delegate.setUniform(var, v1, v2, v3);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, int v1, int v2, int v3, int v4) {
+        delegate.setUniform(var, v1, v2, v3, v4);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, boolean val) {
+        delegate.setUniform(var, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, boolean v1, boolean v2) {
+        delegate.setUniform(var, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, boolean v1, boolean v2, boolean v3) {
+        delegate.setUniform(var, v1, v2, v3);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, boolean v1, boolean v2, boolean v3, boolean v4) {
+        delegate.setUniform(var, v1, v2, v3, v4);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, Sampler texture) {
+        delegate.setUniform(var, texture);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, @Const ColorRGB color) {
+        delegate.setUniform(var, color);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniform(Shader.Uniform var, @Const ColorRGB color, boolean isHDR) {
+        delegate.setUniform(var, color, isHDR);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, VertexAttribute attr) {
+        delegate.bindAttributeArray(var, index, attr);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, int column, VertexAttribute attr) {
+        delegate.bindAttributeArray(var, index, column, attr);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, double val) {
+        delegate.bindAttributeArray(var, index, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, double v1, double v2) {
+        delegate.bindAttributeArray(var, index, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, @Const Vector3 v) {
+        delegate.bindAttributeArray(var, index, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, @Const Vector4 v) {
+        delegate.bindAttributeArray(var, index, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, double m00, double m01, double m10,
+                                   double m11) {
+        delegate.bindAttributeArray(var, index, m00, m01, m10, m11);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, @Const Matrix3 v) {
+        delegate.bindAttributeArray(var, index, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, @Const Matrix4 v) {
+        delegate.bindAttributeArray(var, index, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, int val) {
+        delegate.bindAttributeArray(var, index, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, int v1, int v2) {
+        delegate.bindAttributeArray(var, index, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, int v1, int v2, int v3) {
+        delegate.bindAttributeArray(var, index, v1, v2, v3);
+        checkGLErrors();
+    }
+
+    @Override
+    public void bindAttributeArray(Shader.Attribute var, int index, int v1, int v2, int v3, int v4) {
+        delegate.bindAttributeArray(var, index, v1, v2, v3, v4);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, double val) {
+        delegate.setUniformArray(var, index, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, double v1, double v2) {
+        delegate.setUniformArray(var, index, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, @Const Vector3 v) {
+        delegate.setUniformArray(var, index, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, @Const Vector4 v) {
+        delegate.setUniformArray(var, index, v);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, double m00, double m01, double m10,
+                                double m11) {
+        delegate.setUniformArray(var, index, m00, m01, m10, m11);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, @Const Matrix3 val) {
+        delegate.setUniformArray(var, index, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, @Const Matrix4 val) {
+        delegate.setUniformArray(var, index, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, int val) {
+        delegate.setUniformArray(var, index, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, int v1, int v2) {
+        delegate.setUniformArray(var, index, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, int v1, int v2, int v3) {
+        delegate.setUniformArray(var, index, v1, v2, v3);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, int v1, int v2, int v3, int v4) {
+        delegate.setUniformArray(var, index, v1, v2, v3, v4);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, boolean val) {
+        delegate.setUniformArray(var, index, val);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, boolean v1, boolean v2) {
+        delegate.setUniformArray(var, index, v1, v2);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, boolean v1, boolean v2, boolean v3) {
+        delegate.setUniformArray(var, index, v1, v2, v3);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, boolean v1, boolean v2, boolean v3,
+                                boolean v4) {
+        delegate.setUniformArray(var, index, v1, v2, v3, v4);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, Sampler texture) {
+        delegate.setUniformArray(var, index, texture);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, @Const ColorRGB color) {
+        delegate.setUniformArray(var, index, color);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setUniformArray(Shader.Uniform var, int index, @Const ColorRGB color, boolean isHDR) {
+        delegate.setUniformArray(var, index, color, isHDR);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setPointAntiAliasingEnabled(boolean enable) {
+        delegate.setPointAntiAliasingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLineAntiAliasingEnabled(boolean enable) {
+        delegate.setLineAntiAliasingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setPolygonAntiAliasingEnabled(boolean enable) {
+        delegate.setPolygonAntiAliasingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setPointSize(double width) {
+        delegate.setPointSize(width);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setLineSize(double width) {
+        delegate.setLineSize(width);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilUpdate(StencilUpdate stencilFail, StencilUpdate depthFail,
+                                 StencilUpdate depthPass) {
+        delegate.setStencilUpdate(stencilFail, depthFail, depthPass);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilUpdateFront(StencilUpdate stencilFail, StencilUpdate depthFail,
+                                      StencilUpdate depthPass) {
+        delegate.setStencilUpdateFront(stencilFail, depthFail, depthPass);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilUpdateBack(StencilUpdate stencilFail, StencilUpdate depthFail,
+                                     StencilUpdate depthPass) {
+        delegate.setStencilUpdateBack(stencilFail, depthFail, depthPass);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTest(Comparison test, int refValue, int testMask) {
+        delegate.setStencilTest(test, refValue, testMask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTestFront(Comparison test, int refValue, int testMask) {
+        delegate.setStencilTestFront(test, refValue, testMask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTestBack(Comparison test, int refValue, int testMask) {
+        delegate.setStencilTestBack(test, refValue, testMask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilTestEnabled(boolean enable) {
+        delegate.setStencilTestEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilWriteMask(int mask) {
+        delegate.setStencilWriteMask(mask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setStencilWriteMask(int front, int back) {
+        delegate.setStencilWriteMask(front, back);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthTest(Comparison test) {
+        delegate.setDepthTest(test);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthWriteMask(boolean mask) {
+        delegate.setDepthWriteMask(mask);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthOffsets(double factor, double units) {
+        delegate.setDepthOffsets(factor, units);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDepthOffsetsEnabled(boolean enable) {
+        delegate.setDepthOffsetsEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDrawStyle(DrawStyle style) {
+        delegate.setDrawStyle(style);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setDrawStyle(DrawStyle front, DrawStyle back) {
+        delegate.setDrawStyle(front, back);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setColorWriteMask(boolean red, boolean green, boolean blue, boolean alpha) {
+        delegate.setColorWriteMask(red, green, blue, alpha);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendingEnabled(boolean enable) {
+        delegate.setBlendingEnabled(enable);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendColor(@Const Vector4 color) {
+        delegate.setBlendColor(color);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendMode(BlendFunction function, BlendFactor src, BlendFactor dst) {
+        delegate.setBlendMode(function, src, dst);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendModeRGB(BlendFunction function, BlendFactor src, BlendFactor dst) {
+        delegate.setBlendModeRGB(function, src, dst);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setBlendModeAlpha(BlendFunction function, BlendFactor src, BlendFactor dst) {
+        delegate.setBlendModeAlpha(function, src, dst);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setIndices(ElementBuffer indices) {
+        delegate.setIndices(indices);
+        checkGLErrors();
+    }
+
+    @Override
+    public int render(PolygonType polyType, int offset, int count) {
+        int rendered = delegate.render(polyType, offset, count);
+        checkGLErrors();
+        return rendered;
+    }
+
+    @Override
+    public void reset() {
+        delegate.reset();
+        checkGLErrors();
+    }
+
+    @Override
+    public void clear(boolean clearColor, boolean clearDepth, boolean clearStencil) {
+        delegate.clear(clearColor, clearDepth, clearStencil);
+        checkGLErrors();
+    }
+
+    @Override
+    public void clear(boolean clearColor, boolean clearDepth, boolean clearStencil, @Const Vector4 color,
+                      double depth, int stencil) {
+        delegate.clear(clearColor, clearDepth, clearStencil, color, depth, stencil);
+        checkGLErrors();
+    }
+
+    @Override
+    public void setViewport(int x, int y, int width, int height) {
+        delegate.setViewport(x, y, width, height);
+        checkGLErrors();
+    }
+}

File ferox-renderer/src/main/java/com/ferox/renderer/impl/FrameworkImpl.java

  */
 public class FrameworkImpl implements Framework {
     private final ManagedFramework impl;
-    private Capabilities renderCaps; // final after initialize() has been called.
+    private final boolean debugMode;
 
     // fullscreen support
     private volatile WeakReference<OnscreenSurface> fullscreenSurface;
             throw new NullPointerException("ResourceFactory cannot be null");
         }
 
+        debugMode = Boolean.getBoolean(Factory.DEBUG_PROPERTY);
         ContextManager contextManager = new ContextManager();
         impl = new ManagedFramework(surfaceFactory, new LifeCycleManager(getClass().getSimpleName()),
                                     new DestructibleManager(), resourceFactory, contextManager);
 
                 // register this framework to be auto-destroyed
                 impl.destructibleManager.manage(FrameworkImpl.this, impl);
-
-                renderCaps = impl.surfaceFactory.getCapabilities();
             }
         });
     }
 
     @Override
     public Capabilities getCapabilities() {
-        return renderCaps;
+        return impl.surfaceFactory.getCapabilities();
     }
 
     @Override
 
         @Override
         public T call() throws Exception {
-            T value = task.run(new HardwareAccessLayerImpl(FrameworkImpl.this));
+            T value = task.run(new HardwareAccessLayerImpl(FrameworkImpl.this, debugMode));
             OpenGLContext ctx = impl.contextManager.getCurrentContext();
             if (ctx != null) {
                 String error = ctx.checkGLErrors();

File ferox-renderer/src/main/java/com/ferox/renderer/impl/HardwareAccessLayerImpl.java

  */
 public class HardwareAccessLayerImpl implements HardwareAccessLayer {
     private final FrameworkImpl framework;
+    private final boolean useDebugRenderers;
 
     private ContextImpl currentContext;
 
-    public HardwareAccessLayerImpl(FrameworkImpl framework) {
+    public HardwareAccessLayerImpl(FrameworkImpl framework, boolean useDebugRenderers) {
         this.framework = framework;
+        this.useDebugRenderers = useDebugRenderers;
     }
 
     @Override
         @Override
         public GlslRenderer getGlslRenderer() {
             if (selectedRenderer == null) {
-                // need to select a renderer
+                // activate the glsl renderer
                 selectedRenderer = context.getGlslRenderer();
                 if (selectedRenderer instanceof Activateable) {
                     ((Activateable) selectedRenderer).activate(surface);
                 }
+
+                // we wrap in debug mode afterwards because it does not implement activateable
+                if (useDebugRenderers) {
+                    selectedRenderer = new DebugGlslRenderer(context, (GlslRenderer) selectedRenderer);
+                }
+
                 selectedRenderer.reset();
             }
 
         @Override
         public FixedFunctionRenderer getFixedFunctionRenderer() {
             if (selectedRenderer == null) {
-                // need to select a renderer
+                // activate the ffp renderer
                 selectedRenderer = context.getFixedFunctionRenderer();
                 if (selectedRenderer instanceof Activateable) {
                     ((Activateable) selectedRenderer).activate(surface);
                 }
+
+                // we wrap in debug mode afterwards because it does not implement activateable
+                if (useDebugRenderers) {
+                    selectedRenderer = new DebugFixedFunctionRenderer(context,
+                                                                      (FixedFunctionRenderer) selectedRenderer);
+                }
+
                 selectedRenderer.reset();
             }
 

File ferox-renderer/src/main/java/com/ferox/renderer/impl/ShaderFixedFunctionEmulator.java

     }
 
     @Override
-    public void setBlendModeRgb(BlendFunction function, BlendFactor src, BlendFactor dst) {
-        glsl.setBlendModeRgb(function, src, dst);
+    public void setBlendModeRGB(BlendFunction function, BlendFactor src, BlendFactor dst) {
+        glsl.setBlendModeRGB(function, src, dst);
     }
 
     @Override