Commits

Michael Ludwig committed f1bdcc9

Write documentation for all of the new resource types, and update old classes to reflect the new API design.

  • Participants
  • Parent commits 8e580dd

Comments (0)

Files changed (34)

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/Buffer.java

 package com.ferox.renderer;
 
 /**
+ * Buffer is the high-level resource type representing an array of bytes stored on the
+ * GPU. Depending on the primitive data type, the bytes are interpreted in different ways,
+ * e.g. as signed or unsigned ints, floats, etc. Depending on how a buffer is used,
+ * different data types are valid. The usage of a buffer is encoded in the type system
+ * where {@link VertexBuffer} or {@link ElementBuffer} are used as appropriate.
  *
+ * @author Michael Ludwig
  */
 public interface Buffer extends Resource {
+    /**
+     * Get the length of the buffer. The length of the buffer will not change over time.
+     * It is possible to use a shorter sequence of elements and a dynamic buffer to
+     * support buffers that shrink and grow within the upper bound of {@code length}. If a
+     * larger buffer is required, a new one must be initialized through the framework.
+     * <p/>
+     * The length is measured in units of the data type. Thus the total number of bytes is
+     * {@code getLength() * getDataType().getByteCount()}.
+     *
+     * @return The maximum number of primitive elements in the buffer
+     */
     public int getLength();
 
+    /**
+     * @return The primitive interpretation of the bytes within the buffer
+     */
     public DataType getDataType();
 }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/Capabilities.java

+/*
+ * Ferox, a graphics and game library in Java
+ *
+ * Copyright (c) 2012, Michael Ludwig
+ * 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.
+ *
+ * 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 HOLDER 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.ferox.renderer;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * <p/>
+ * Capabilities holds onto a set of different parameters describing more advanced features
+ * that the baseline hardware may not support.
+ * <p/>
+ * Because Ferox was designed to be implemented with an OpenGL system, the capabilities
+ * here reflect that and allow for lower-level inspection of the current hardware.
+ * Framework implementations are expected to extend Capabilities to provide the correct
+ * values for each parameter. Capabilities instances returned from {@link
+ * com.ferox.renderer.Framework#getCapabilities()} can be considered immutable.
+ *
+ * @author Michael Ludwig
+ */
+public abstract class Capabilities {
+    // texture properties
+    protected int maxVertexShaderTextures = -1; //
+    protected int maxFragmentShaderTextures = -1; //
+    protected int maxFixedPipelineTextures = -1; //
+    protected int maxCombinedTextures = -1; //
+
+    protected float maxAnisoLevel = 0f; //
+
+    protected boolean hasDepthTextures = false; //
+    protected boolean hasDepthStencilTextures = false; //
+    protected boolean hasEnvCombine = false; //
+    protected boolean hasMirrorRepeat = false; //
+    protected boolean hasClampEdge = false; //
+
+    // texture + renderbuffer dimensions
+    protected int maxTextureSize = 0; //
+    protected int maxTextureCubeMapSize = 0; //
+    protected int maxTexture3DSize = 0; //
+    protected int maxRenderbufferSize = 0; //
+
+    // type of supported textures
+    protected boolean fpTextures = false; //
+    protected boolean npotTextures = false; //
+    protected boolean s3tcTextures = false; //
+
+    protected Set<Class<? extends Sampler>> supportedTargets = Collections.emptySet(); //
+
+    // geometry properties
+    protected int maxVertexAttributes = 0; //
+    protected int maxTextureCoordinates = 0; //
+    protected boolean vboSupported = false; //
+
+    // misc
+    protected int maxActiveLights = 0; //
+    protected boolean blendSupported = false; //
+    protected boolean hasSeparateBlend = false; //
+    protected boolean hasSeparateStencil = false; //
+
+    protected boolean hasFfpRenderer = false; //
+
+    // glsl
+    protected boolean hasGlslRenderer = false; //
+    protected boolean geometryShaderSupport = false; //
+    protected int glslVersion;
+
+    protected String vendor = ""; //
+    protected int majorVersion = 0;
+    protected int minorVersion = 0;
+
+    // frame properties
+    protected boolean fboSupported = false; //
+    protected boolean pbuffersSupported = false; //
+    protected int maxColorTargets = 0; //
+    protected int[] depthBufferSizes = new int[1]; //
+    protected int[] stencilBufferSizes = new int[1]; //
+    protected int[] msaaSamples = new int[1]; //
+
+    protected DisplayMode[] availableModes = new DisplayMode[0]; //
+
+    protected boolean supportsMultipleOnscreenSurfaces;
+
+    /**
+     * @return True if multiple non-fullscreen onscreen surfaces can exist at the same
+     *         time with this framework
+     */
+    public boolean getMultipleOnscreenSurfaceSupport() {
+        return supportsMultipleOnscreenSurfaces;
+    }
+
+    /**
+     * Return an array of available DisplayModes that can be used when creating fullscreen
+     * surfaces with {@link Framework#createSurface(OnscreenSurfaceOptions)}. A defensive
+     * array copy is returned, with no particular ordering. If the returned array is
+     * empty, fullscreen surfaces are not supported.
+     *
+     * @return All available display modes on the system
+     */
+    public DisplayMode[] getAvailableDisplayModes() {
+        return Arrays.copyOf(availableModes, availableModes.length);
+    }
+
+    /**
+     * Return an array of the depth buffer bit sizes that are supported on this hardware.
+     * The returned array is ordered from least to greatest bit size and is a defensive
+     * copy. The array will always contain the value 0 for no depth buffer support.
+     *
+     * @return Supported depth buffer sizes
+     */
+    public int[] getAvailableDepthBufferSizes() {
+        return Arrays.copyOf(depthBufferSizes, depthBufferSizes.length);
+    }
+
+    /**
+     * Return an array of the stencil buffer bit sizes that are supported on this
+     * hardware. The returned array is ordered from least to greatest bit size and is a
+     * defensive copy. The array will always at least contain the value 0 for no stencil
+     * buffer support.
+     *
+     * @return Supported stencil buffer sizes
+     */
+    public int[] getAvailableStencilBufferSizes() {
+        return Arrays.copyOf(stencilBufferSizes, stencilBufferSizes.length);
+    }
+
+    /**
+     * Return an array of the sample counts that are supported on this hardware when using
+     * MSAA. The returned array is ordered from least to greatest bit size and is a
+     * defensive copy. The array will always contain the value 0 for no MSAA support.
+     *
+     * @return Supported MSAA sample counts
+     */
+    public int[] getAvailableSamples() {
+        return Arrays.copyOf(msaaSamples, msaaSamples.length);
+    }
+
+    /**
+     * @return True if the blending operation exposed in {@link Renderer} is supported.
+     */
+    public boolean isBlendingSupported() {
+        return blendSupported;
+    }
+
+    /**
+     * @return The set of supported sampler interfaces on this hardware.
+     */
+    public Set<Class<? extends Sampler>> getSupportedTextureTargets() {
+        return supportedTargets;
+    }
+
+    /**
+     * @return True if the DEPTH BaseFormat is supported
+     */
+    public boolean getDepthTextureSupport() {
+        return hasDepthTextures;
+    }
+
+    /**
+     * @return True if the DEPTH_STENCIL BaseFormat is supported
+     */
+    public boolean getDepthStencilTextureSupport() {
+        return hasDepthStencilTextures;
+    }
+
+    /**
+     * @return True if the COMBINE EnvMode is supported by FixedFunctionRenderers
+     */
+    public boolean getCombineEnvModeSupport() {
+        return hasEnvCombine;
+    }
+
+    /**
+     * @return True if the MIRROR WrapMode is supported
+     */
+    public boolean getMirrorWrapModeSupport() {
+        return hasMirrorRepeat;
+    }
+
+    /**
+     * @return True if the CLAMP WrapMode can use the GL_CLAMP_TO_EDGE extension, which
+     *         improves appearance, or false when it must fallback to GL_CLAMP
+     */
+    public boolean getClampToEdgeSupport() {
+        return hasClampEdge;
+    }
+
+    /**
+     * @return True if blending can be correctly separated across front and back facing
+     *         polygons.
+     */
+    public boolean getSeparateBlendSupport() {
+        return hasSeparateBlend;
+    }
+
+    /**
+     * @return True if stencil operations can be correctly separated across front and back
+     *         facing polygons.
+     */
+    public boolean getSeparateStencilSupport() {
+        return hasSeparateStencil;
+    }
+
+    /**
+     * Return the maximum side dimension of a Texture1D, Texture2D, or DepthMap2D.
+     *
+     * @return Maximum size of a 1d or 2d texture
+     */
+    public int getMaxTextureSize() {
+        return maxTextureSize;
+    }
+
+    /**
+     * Return the maximum side dimension of a Texture3D.
+     *
+     * @return Maximum size of a 3d texture
+     */
+    public int getMaxTexture3DSize() {
+        return maxTexture3DSize;
+    }
+
+    /**
+     * Return the maximum side dimension of a face of a TextureCubeMap or a DepthCubeMap.
+     *
+     * @return Maximum size of a cube map
+     */
+    public int getMaxTextureCubeMapSize() {
+        return maxTextureCubeMapSize;
+    }
+
+    /**
+     * Return the maximum dimension of any Texture used with a TextureSurface.
+     *
+     * @return Maximum dimension of a TextureSurface
+     */
+    public int getMaxTextureSurfaceSize() {
+        return maxRenderbufferSize;
+    }
+
+    /**
+     * Return the maximum number of color buffers that can be rendered into simultaneously
+     * with a GLSL program when using a TextureSurface.
+     *
+     * @return Number of color targets allowed for TextureSurfaces
+     */
+    public int getMaxColorBuffers() {
+        return maxColorTargets;
+    }
+
+    /**
+     * Get max number of textures allowed in the vertex shader stage of a GLSL program.
+     * This will return a number <= 0 if GLSL shaders are not supported.
+     *
+     * @return Number of textures allowed in a vertex shader
+     */
+    public int getMaxVertexShaderTextures() {
+        return maxVertexShaderTextures;
+    }
+
+    /**
+     * Get the max number of textures allowed in the fragment shader of GLSL program. This
+     * will return a number <= 0 if GLSL shaders are not supported.
+     *
+     * @return Number of textures allowed in a fragment shader
+     */
+    public int getMaxFragmentShaderTextures() {
+        return maxFragmentShaderTextures;
+    }
+
+    /**
+     * Get the max number of textures usable by a {@link FixedFunctionRenderer}. Textures
+     * beyond this will be ignored when using a fixed function renderer, GLSL renderers
+     * may support more available textures.
+     *
+     * @return Total number of textures usable in fixed-function
+     */
+    public int getMaxFixedPipelineTextures() {
+        return maxFixedPipelineTextures;
+    }
+
+    /**
+     * Get the max number of textures used by an entire GLSL program. This may be less
+     * than the sum of {@link #getMaxVertexShaderTextures()} and {@link
+     * #getMaxFragmentShaderTextures()}.
+     *
+     * @return Total number of texture samplers in a GLSL program
+     */
+    public int getMaxCombinedTextures() {
+        return maxCombinedTextures;
+    }
+
+    /**
+     * Get the max supported level of anisotropic filtering for textures. If anisotropic
+     * filtering is not supported, this should return a number <= 0. A value of 1 in
+     * {@link com.ferox.renderer.Texture#getAnisotropicFiltering()} will be scaled by the
+     * Framework to the returned number.
+     *
+     * @return Maximum level of anistropic filtering
+     */
+    public float getMaxAnisotropicLevel() {
+        return maxAnisoLevel;
+    }
+
+    /**
+     * Whether or not unclamped floating point textures are supported. If false, float
+     * texture values are clamped to be within 0 to 1.
+     *
+     * @return If full floating point textures can be stored
+     */
+    public boolean getUnclampedFloatTextureSupport() {
+        return fpTextures;
+    }
+
+    /**
+     * Whether or not non-power of two dimensions are supported for textures.
+     *
+     * @return If NPOT texturing is available for 1d, 2d, 3d and cube map textures
+     */
+    public boolean getNPOTTextureSupport() {
+        return npotTextures;
+    }
+
+    /**
+     * Whether or not the S3TC extension is present. This allows for DXT1, DXT3, and DXT5
+     * texture compression on the graphics card.
+     *
+     * @return If DXT texture compression is supported
+     */
+    public boolean getS3TextureCompression() {
+        return s3tcTextures;
+    }
+
+    /**
+     * Get the maximum vertex attributes allowed on each vertex rendered.
+     *
+     * @return Number of vertex attributes
+     */
+    public int getMaxVertexAttributes() {
+        return maxVertexAttributes;
+    }
+
+    /**
+     * Get the maximum number of texture coordinates for each vertex. This may be
+     * different then the maximum number of textures.
+     *
+     * @return Number of texture coordinates
+     */
+    public int getMaxTextureCoordinates() {
+        return maxTextureCoordinates;
+    }
+
+    /**
+     * Whether or not vertex and element buffers stored directly on the GPU are
+     * supported.
+     *
+     * @return True if non-dynamic buffers can be cached to the GPU
+     */
+    public boolean getVertexBufferSupport() {
+        return vboSupported;
+    }
+
+    /**
+     * Get the maximum number of lights that can affect a rendered object at one time when
+     * using a {@link FixedFunctionRenderer}.
+     *
+     * @return Total number of simultaneous lights
+     */
+    public int getMaxActiveLights() {
+        return maxActiveLights;
+    }
+
+    /**
+     * Whether or not this Framework can provide Renderers that implement {@link
+     * GlslRenderer}.
+     *
+     * @return True if shaders can be used
+     */
+    public boolean hasGlslRenderer() {
+        return hasGlslRenderer;
+    }
+
+    /**
+     * Whether or not this Framework can provide Renderers that implement {@link
+     * FixedFunctionRenderer}.
+     *
+     * @return True if fixed-function pipeline can be used
+     */
+    public boolean hasFixedFunctionRenderer() {
+        return hasFfpRenderer;
+    }
+
+    /**
+     * Whether or not offscreen surfaces can be implemented using frame buffer objects,
+     * which is significantly faster than relying on pbuffers.
+     *
+     * @return True if fbos can be used
+     */
+    public boolean getFBOSupport() {
+        return fboSupported;
+    }
+
+    /**
+     * Whether or not pbuffers (different than pixel buffers) are supported for offscreen
+     * surfaces. Pbuffers are slower than fbos but are supported on more hardware.
+     *
+     * @return True if pbuffers can be used
+     */
+    public boolean getPBufferSupport() {
+        return pbuffersSupported;
+    }
+
+    /**
+     * Get the vendor returned string that describes the OpenGL drivers installed on the
+     * computer.
+     *
+     * @return Implementation vendor description
+     */
+    public String getVendor() {
+        return vendor;
+    }
+
+    /**
+     * @return The OpenGL major version present on the computer
+     */
+    public int getMajorVersion() {
+        return majorVersion;
+    }
+
+    /**
+     * @return The OpenGL minor version present on the computer
+     */
+    public int getMinorVersion() {
+        return minorVersion;
+    }
+
+    /**
+     * Get the GLSL shading language available on the computer. If {@link
+     * #hasGlslRenderer()} returns false, this value is undefined. The reported version is
+     * the integer value used in the #version declaration in source code. Example: for
+     * GLSL 1.4 the returned value is 140, for 3.3 it is 330.
+     *
+     * @return Version in integer form
+     */
+    public int getGlslVersion() {
+        return glslVersion;
+    }
+
+    /**
+     * @return True if the GlslRenderer can support shaders with a geometry shader.
+     *         Shaders always support vertex and fragment shaders.
+     */
+    public boolean hasGeometryShaderSupport() {
+        return geometryShaderSupport;
+    }
+}

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/Context.java

  * Surface. It also controls when the rendered contents of the Surface are flushed to
  * their final destination (e.g. visible window or texture). When executing Tasks, a
  * HardwareAccessLayer is provided; the HardwareAccessLayer provides Contexts by calling
- * its setActiveSurface() methods. Within a Task, only a single context can be active at
- * one time. Multiple contexts can be used in one Task, although old contexts will be
+ * its setActiveSurface() methods. Within a Task, only a single context can be active at a
+ * time. Multiple contexts can be used in one Task, although old contexts will be
  * invalidated when setActiveSurface() is called again.
  *
  * @author Michael Ludwig
      * Return a GlslRenderer to render into the surface that is currently in use. This
      * will return null if the Context cannot support a GlslRenderer. Tasks can only use
      * one renderer per returned Context. The Surface that provided this context must be
-     * re-activated to reset the context to get at a different renderer if needed.
+     * re-activated to get at a different renderer type.
      * <p/>
      * A GlslRenderer and FixedFunctionRenderer cannot be used at the same time. If this
      * is called after a call to {@link #getFixedFunctionRenderer()} on the same context,
      * <p/>
      * Return a FixedFunctionRenderer to render into the surface that is currently in use.
      * This will return null if the Context cannot support a FixedFunctionRenderer. Tasks
-     * can only use a one renderer per returned Context. The Surface that provided this
-     * context must be re-activated to reset the context to get at a different renderer if
-     * needed.
+     * can only use one renderer per returned Context. The Surface that provided this
+     * context must be re-activated to to get a different renderer type.
      * <p/>
      * A FixedFunctionRenderer and GlslRenderer cannot be used at the same time. If this
      * is called after a call to {@link #getGlslRenderer()} on the same context, an
      * rendered into directly. This method should be called regardless of type of surface
      * because Tasks cannot know before hand what flushing will do.
      * <p/>
-     * If rendering is done across in multiple tasks, a flush only needs to be performed
-     * in the last pass. Alternatively, {@link Framework#flush(Surface)} can be used as a
+     * If rendering is done over multiple tasks, a flush only needs to be performed in the
+     * last pass. Alternatively, {@link Framework#flush(Surface)} can be used as a
      * convenience.
      */
     public void flush();
 
     /**
      * Get the Surface that was the argument to {@link HardwareAccessLayer#setActiveSurface(Surface)}
-     * or {@link HardwareAccessLayer#setActiveSurface(TextureSurface, int)} that initially
-     * produced this Context.
+     * and other setActiveSurface() methods that produced this Context.
      *
      * @return The Surface for this context
      */

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/DataType.java

 package com.ferox.renderer;
 
 /**
- * DataType represents the supported set of primitive data types that can be transfered to
- * the GPU. The type system leveraged by GPUs is more extensive than what is available in
- * Java. To account for this, common data interpretations are specified in this enum to
+ * DataType represents the supported set of primitive data types that can be transferred
+ * to the GPU. The type system leveraged by GPUs is more extensive than what is available
+ * in Java. To account for this, common data interpretations are specified in this enum to
  * map from Java's primitives to the majority of types needed. If the GPU requires a more
  * complex type, the {@link DataType#INT_BIT_FIELD} value represents arbitrary 32-bit
  * patterns.
  * @author Michael Ludwig
  */
 public enum DataType {
+    /**
+     * The 4 bytes are treated as the IEEE floating point standard, e.g. the same as
+     * Java.
+     */
     FLOAT(4, float.class, true, true),
+    /**
+     * The 2 bytes are treated as the OpenGL 16-bit half-float with 1 bit for sign, 5 bits
+     * for exponent, and 10 bits for a mantissa.
+     */
     HALF_FLOAT(2, short.class, true, true),
+    /**
+     * The 4 bytes are treated as the standard two's-complement signed 32-bit integer,
+     * e.g. the same as Java.
+     */
     INT(4, int.class, false, true),
+    /**
+     * The 4 bytes are treated as a one's-complement 32-bit unsigned integer. The sign-bit
+     * in the Java representation is treated as the most significant bit instead of a
+     * sign.
+     */
     UNSIGNED_INT(4, int.class, false, false),
+    /**
+     * The 4 bytes are evaluated identically to INT, and then normalized to the decimal
+     * range [-1.0, 1.0].
+     */
     NORMALIZED_INT(4, int.class, true, true),
+    /**
+     * The 4 bytes are evaluated identically to UNSIGNED_INT, and then normalized to the
+     * decimal range [0.0, 1.0].
+     */
     UNSIGNED_NORMALIZED_INT(4, int.class, true, false),
+    /**
+     * The 2 bytes are evaluated as the standard two's-complement signed 16-bit integer,
+     * e.g. the same as Java.
+     */
     SHORT(2, short.class, false, true),
+    /**
+     * The 2 bytes are evaluated as a one's complement 16-bit unsigned integer. The
+     * sign-bit in the Java representation is treated as the most significant bit.
+     */
     UNSIGNED_SHORT(2, short.class, false, false),
+    /**
+     * The 2 bytes are evaluated identically to SHORT, and then normalized to the decimal
+     * range [-1.0, 1.0].
+     */
     NORMALIZED_SHORT(2, short.class, true, true),
+    /**
+     * The 2 bytes are evaluated identically to UNSIGNED_SHORT, and then normalized to the
+     * decimal range [0.0, 1.0].
+     */
     UNSIGNED_NORMALIZED_SHORT(2, short.class, true, false),
+    /**
+     * The single byte is evaluated as the standard two's-complement signed 8-bit integer,
+     * e.g. the same as Java.
+     */
     BYTE(1, byte.class, false, true),
+    /**
+     * The single byte is evaluated as a one's complement 8-bit unsigned integer. The
+     * sign-bit in the Java representation is treated as the most significant bit.
+     */
     UNSIGNED_BYTE(1, byte.class, false, false),
+    /**
+     * The single byte is evaluated identically to BYTE, and then normalized to the
+     * decimal range [-1.0, 1.0].
+     */
     NORMALIZED_BYTE(1, byte.class, true, true),
+    /**
+     * The single byte is evaluated identically to UNSIGNED_BYTE, and then normalized to
+     * the decimal range [0.0, 1.0].
+     */
     UNSIGNED_NORMALIZED_BYTE(1, byte.class, true, false),
+    /**
+     * The 4 bytes are interpreted in a context-specific manner. The 32-bit Java int is
+     * merely a vehicle to deliver those bits to OpenGL. This is most common with packed
+     * texture formats such as DEPTH_STENCIL where 24 bits are the depth, and 8 are the
+     * stencil; another example is the ARGB texture format with 8 bits per component
+     * packed into a single integer.
+     */
     INT_BIT_FIELD(4, int.class, false, false);
 
     private final int byteCount;

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/DepthCubeMap.java

 package com.ferox.renderer;
 
 /**
+ * DepthCubeMap is a DepthMap that has six separate two dimensional images storing depth
+ * and optionally stencil data. Each face can be used as a depth/stencil render target for
+ * render-to-texture with a {@link TextureSurface}. All six images have the same width and
+ * height so they represent the six faces of a cube. Shaders can refer to a DepthCubeMap
+ * in the GLSL code with the 'samplerCubeShadow' uniform type.
  *
+ * @author Michael Ludwig
+ * @see TextureCubeMap
  */
 public interface DepthCubeMap extends DepthMap {
+    /**
+     * @return A RenderTarget that renders into the positive-x face of the cube
+     */
     public RenderTarget getPositiveXRenderTarget();
 
+    /**
+     * @return A RenderTarget that renders into the negative-x face of the cube
+     */
     public RenderTarget getNegativeXRenderTarget();
 
+    /**
+     * @return A RenderTarget that renders into the positive-y face of the cube
+     */
     public RenderTarget getPositiveYRenderTarget();
 
+    /**
+     * @return A RenderTarget that renders into the negative-x face of the cube
+     */
     public RenderTarget getNegativeYRenderTarget();
 
+    /**
+     * @return A RenderTarget that renders into the positive-z face of the cube
+     */
     public RenderTarget getPositiveZRenderTarget();
 
+    /**
+     * @return A RenderTarget that renders into the negative-z face of the cube
+     */
     public RenderTarget getNegativeZRenderTarget();
 }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/DepthMap.java

 package com.ferox.renderer;
 
 /**
+ * DepthMaps are samplers that store depth and possibly stencil data instead of color
+ * data. They are commonly used for shadow-mapping and deferred rendering techniques. They
+ * can also be used to provide the depth buffer when doing any render-to-texture technique
+ * that might need the same depth buffer later on.
+ * <p/>
+ * All DepthMap instances will return DEPTH or DEPTH_STENCIL as their base format.
  *
+ * @author Michael Ludwig
  */
 public interface DepthMap extends Sampler {
-    public boolean isDepthComparisonEnabled();
+    /**
+     * Get the comparison function used. If a null value is returned, the depth-comparison
+     * operation is not performed and depth values are returned from the sampler as is.
+     * Otherwise, the the depth value is compared with the texture coordinate and a 0 or 1
+     * is returned depending on the result.
+     *
+     * @return The comparison, or null if it's disabled
+     */
+    public Renderer.Comparison getDepthComparison();
 
-    public Renderer.Comparison getDepthComparison();
+    // FIXME how do we specify the "border depth"?
 }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/DepthMap2D.java

 package com.ferox.renderer;
 
 /**
+ * DepthMap2D is a depth map for a single two dimensional image. It can be square or
+ * rectangular. It has a single render target that can be used as a the depth/stencil
+ * target for a {@link TextureSurface}. Shaders can refer to a DepthMap2D in the GLSL code
+ * with the 'sampler2DShadow' uniform type.
  *
+ * @author Michael Ludwig
+ * @see Texture2D
  */
 public interface DepthMap2D extends DepthMap {
+    /**
+     * @return The render target to render directly into the depth map
+     */
     public RenderTarget getRenderTarget();
 }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/Destructible.java

 import java.util.concurrent.Future;
 
 /**
+ * Destructibles are objects that have internal, potentially heavyweight data tied to the
+ * GPU and generally an implementation dependent internal framework thread, similar to how
+ * the AWT EDT thread functions. Destructibles will always be properly disposed of and
+ * cleaned up if they are garbage-collected by the JVM. However, they expose a {@link
+ * #destroy()} method to give more explicit control over the timing of the potentially
+ * expensive task of cleaning up the underlying GPU resources.
  *
+ * @author Michael Ludwig
  */
 public interface Destructible {
+    /**
+     * Manually trigger the destruction of the resource if it's critical the internal
+     * structures are disposed of ASAP instead of waiting for the garbage collector to
+     * detect when it is weak reference-able. All Destructibles will have their internal
+     * structures disposed of when they are weak reference-able but this provides more
+     * control.
+     * <p/>
+     * This method is thread safe and can be called on the Framework's internal thread or
+     * not.  If called on the Framework's internal thread the destruction will occur
+     * immediately and the returned Future will already be completed.  Otherwise the
+     * disposal will be queued into the Framework's internal thread.
+     * <p/>
+     * Regardless of when the internal resources are actually disposed of, this instance
+     * is considered destroyed immediately upon calling this method. When destroyed, all
+     * behavior besides calling destroy() or {@link #isDestroyed()} is undefined.
+     *
+     * @return A Future to check when destruction has completed
+     */
     public Future<Void> destroy();
 
+    /**
+     * @return True if {@link #destroy()} has been invoked manually
+     */
     public boolean isDestroyed();
 }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/DisplayMode.java

 
 /**
  * DisplayMode is an immutable object describing screen dimensions, color bit depth and
- * refresh rate for a monitor display.
+ * refresh rate for a monitor display. This class provides a common-sense implementation
+ * of {@link #equals(Object)} and {@link #hashCode()}.
  *
  * @author Michael Ludwig
  */
         return height;
     }
 
+    /**
+     * @return The number of bits representing color in each pixel
+     */
     public int getBitDepth() {
         return bitDepth;
     }
 
+    /**
+     * @return The refresh rate of the monitor
+     */
     public int getRefreshRate() {
         return refreshRate;
     }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/ElementBuffer.java

 package com.ferox.renderer;
 
 /**
+ * ElementBuffer is a {@link Buffer} that holds unsigned integer data for performing
+ * indexed drawing.  The integer data contains the indices into the configured {@link
+ * VertexAttribute vertex attributes} that are processed by calls to {@link
+ * Renderer#render(com.ferox.renderer.Renderer.PolygonType, int, int)}.
  *
+ * @author Michael Ludwig
  */
 public interface ElementBuffer extends Buffer {
 }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/FixedFunctionRenderer.java

      * Set whether or not eye-space fogging is enabled. If this is enabled, each rendered
      * pixel's color value is blended with the configured fog color (at the time of the
      * rendering) based on the fog equation. The fog equation can be linear, set with
-     * {@link #setFogLinear(float, float)}, or exponential, set with {@link
-     * #setFogExponential(float, boolean)}.
+     * {@link #setFogLinear(double, double)}, or exponential, set with {@link
+     * #setFogExponential(double, boolean)}.
      * <p/>
      * The default state starts with fog disabled.
      *
      * <p/>
      * Set the fog to use an exponential blending factor with the given density function.
      * Fog will be rendered using an exponential equation until {@link
-     * #setFogLinear(float, float)} is called, which sets it to use linear fog instead.
+     * #setFogLinear(double, double)} is called, which sets it to use linear fog instead.
      * <p/>
      * The fog blend factor is computed two different ways, depending on squared. If
      * squared is true, then it is e^(-density * c), else it is e^(-(density * c)^2),
                             @Const Vector4 emm);
 
     /**
+     * Set just the diffuse material color, leaving the other color properties unchanged.
+     * The default diffuse color is (0.8, 0.8, 0.8, 1).
+     *
+     * @param diff The diffuse color, or solid color when lighting is disabled
+     *
+     * @throws NullPointerException if diff is null
+     * @see #setMaterial(com.ferox.math.Vector4, com.ferox.math.Vector4,
+     *      com.ferox.math.Vector4, com.ferox.math.Vector4)
+     */
+    public void setMaterialDiffuse(@Const Vector4 diff);
+
+    /**
+     * Set just the ambient material color, leaving the other color properties unchanged.
+     * The default ambient color is (0.2, 0.2, 0.2, 1). This color is ignored when
+     * lighting is disabled.
+     *
+     * @param amb The ambient color of the material
+     *
+     * @throws NullPointerException if amb is null
+     * @see #setMaterial(com.ferox.math.Vector4, com.ferox.math.Vector4,
+     *      com.ferox.math.Vector4, com.ferox.math.Vector4)
+     */
+    public void setMaterialAmbient(@Const Vector4 amb);
+
+    /**
+     * Set just the specular material color, leaving the other color properties unchanged.
+     * The default specular color is (0.0, 0.0, 0.0, 1). This color is ignored when
+     * lighting is disabled.
+     *
+     * @param spec The specular color of the material
+     *
+     * @throws NullPointerException if spec is null
+     * @see #setMaterial(com.ferox.math.Vector4, com.ferox.math.Vector4,
+     *      com.ferox.math.Vector4, com.ferox.math.Vector4)
+     */
+    public void setMaterialSpecular(@Const Vector4 spec);
+
+    /**
+     * Set just the emitted light of the material, leaving the other color properties
+     * unchanged. The default emitted color is (0.0, 0.0, 0.0, 1). This color is ignored
+     * when lighting is disabled.
+     *
+     * @param emm The emitted color of the material
+     *
+     * @throws NullPointerException if emm is null
+     * @see #setMaterial(com.ferox.math.Vector4, com.ferox.math.Vector4,
+     *      com.ferox.math.Vector4, com.ferox.math.Vector4)
+     */
+    public void setMaterialEmissive(@Const Vector4 emm);
+
+    /**
      * <p/>
      * Set the material shininess to use when lighting is enabled. This shininess acts as
      * an exponent on the specular intensity, and can be used to increase or dampen the
      * @param color The new constant texture color for the unit
      *
      * @throws NullPointerException      if color is null
-     * @throws IllegalArgumentException  if tex is less than 0
      * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
      *                                   provided index, or if tex is less than 0
      */
      * @param gen The TexCoordSource for all four coordinates
      *
      * @throws NullPointerException      if gen is null
-     * @throws IllegalArgumentException  if tex is less than 0
      * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
      *                                   provided index, or if tex is less than 0
      * @see #setTextureCoordGeneration(int, TexCoord, TexCoordSource)
      * @param gen   The new texture coordinate source
      *
      * @throws NullPointerException      if coord or gen are null
-     * @throws IllegalArgumentException  if tex is less than 0
      * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
      *                                   provided index, or if tex is less than 0
      */
      * @param plane The object plane that's used for this unit and coordinate
      *
      * @throws NullPointerException      if coord or plane are null
-     * @throws IllegalArgumentException  if tex is less than 0
      * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
      *                                   provided index, or if tex is less than 0
      */
     public void setTextureObjectPlane(int tex, TexCoord coord, @Const Vector4 plane);
 
     /**
+     * Set the object plane for S coordinate to the first row of the matrix {@code
+     * planes}, the plane for T to the second row, the plane for R to the third row, and
+     * the plane for Q to the fourth row.
+     *
+     * @param tex    The texture unit
+     * @param planes The matrix holding the 4 plane equations in row-order
+     *
+     * @throws NullPointerException      if planes is null
+     * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
+     *                                   provided index, or if tex is less than 0
+     * @see #setTextureObjectPlane(int, com.ferox.renderer.FixedFunctionRenderer.TexCoord,
+     *      com.ferox.math.Vector4)
+     */
+    public void setTextureObjectPlanes(int tex, @Const Matrix4 planes);
+
+    /**
      * <p/>
      * Set the four values used for the {@link TexCoordSource#EYE} generation for the
      * given coordinate and texture. These four values represent (p1, p2, p3, p4) as
      *              multiplication
      *
      * @throws NullPointerException      if coord or plane are null
-     * @throws IllegalArgumentException  if tex is less than 0
      * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
      *                                   provided index, or if tex is less than 0
      */
     public void setTextureEyePlane(int tex, TexCoord coord, @Const Vector4 plane);
 
     /**
+     * Set the eue plane for S coordinate to the first row of the matrix {@code planes},
+     * the plane for T to the second row, the plane for R to the third row, and the plane
+     * for Q to the fourth row.
+     *
+     * @param tex    The texture unit
+     * @param planes The matrix holding the 4 plane equations in row-order
+     *
+     * @throws NullPointerException      if planes is null
+     * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
+     *                                   provided index, or if tex is less than 0
+     * @see #setTextureEyePlane(int, com.ferox.renderer.FixedFunctionRenderer.TexCoord,
+     *      com.ferox.math.Vector4)
+     */
+    public void setTextureEyePlanes(int tex, @Const Matrix4 planes);
+
+    /**
      * <p/>
      * Set the transform matrix applied to texture coordinates before they are used to
      * lookup texels in the unit's texture image. For multiplication purposes, all
      * @param matrix The texture coordinate transform matrix
      *
      * @throws NullPointerException      if matrix is null
-     * @throws IllegalArgumentException  if tex is less than 0
      * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
      *                                   provided index, or if tex is less than 0
      */
     /**
      * <p/>
      * Set the VertexAttribute that is used as the source of vertex positions when {@link
-     * #render(PolygonType, int, int)} or {@link #render(PolygonType, VertexBufferObject,
-     * int)} is invoked. The attribute must be of type FLOAT. The attribute can have an
-     * element size of 2, 3 or 4. If the 4th component is not provided, it defaults to 1.
-     * If the 3rd component is not provided, it defaults to 0.
+     * #render(PolygonType, int, int)} is invoked. The vertex buffer's data type must
+     * store decimal data. The attribute can have an element size of 2, 3 or 4. If the 4th
+     * component is not provided, it defaults to 1. If the 3rd component is not provided,
+     * it defaults to 0. The vertex elements will be accessed linearly if no indices are
+     * bound, or by the indices in the last bound element buffer.
      * <p/>
      * This updates the currently bound vertex position attribute. The bound attribute
      * will remain unchanged after rendering until this method is called again. Rendering
      * @param vertices The VertexAttribute holding the position data and access
      *                 information
      *
-     * @throws IllegalArgumentException if vertices' buffer data type is not FLOAT or if
-     *                                  its element size is 1
+     * @throws IllegalArgumentException if vertices' element size is 1 or does not hold
+     *                                  decimal data
      */
     public void setVertices(VertexAttribute vertices);
 
     /**
      * <p/>
      * Set the VertexAttribute that is used as a source of normal vectors when {@link
-     * #render(PolygonType, int, int)} or {@link #render(PolygonType,
-     * com.ferox.renderer.geom.VertexBufferObject, int)} is invoked. The attribute type
-     * must be FLOAT. The attribute must have an element size of 3.
+     * #render(PolygonType, int, int)} is invoked. The vertex buffer's data type must
+     * store decimal data. The attribute must have an element size of 3. The normal
+     * elements will be accessed linearly if no indices are bound, or by the indices in
+     * the last bound element buffer.
      * <p/>
      * This updates the currently bound normal attribute. The bound attribute will remain
      * unchanged after rendering until this method is called again. A normals attribute is
      * @param normals The VertexAttribute holding the normal vector data and access
      *                information
      *
-     * @throws IllegalArgumentException if normals element size is not 3 or if its type is
-     *                                  not FLOAT
+     * @throws IllegalArgumentException if normals' element size is not 3 or does not hold
+     *                                  decimal data
      */
     public void setNormals(VertexAttribute normals);
 
     /**
      * <p/>
      * Set the VertexAttribute that provides per-vertex colors when {@link
-     * #render(PolygonType, int, int)} or {@link #render(PolygonType, VertexBufferObject,
-     * int, int)} is invoked. The attribute data type must be FLOAT and its element size
-     * equal to 3 or 4. Values are assumed to be between 0 and 1 to properly represent
-     * packed RGB colors. The first primitive in a vertex's element is the red, the second
-     * is green, and the third is blue. If the element size is 4, the fourth value is the
-     * alpha, otherwise the alpha is set to 1.
+     * #render(PolygonType, int, int)} is invoked. The vertex buffer's data type must
+     * store decimal data, and the attribute's element size equal to 3 or 4. Values are
+     * assumed to be between 0 and 1 to properly represent packed RGB colors. The first
+     * primitive in a vertex's element is the red, the second is green, and the third is
+     * blue. If the element size is 4, the fourth value is the alpha, otherwise the alpha
+     * is set to 1.
      * <p/>
-     * This will replace the diffuse color that specified in {@link #setMaterial(Vector4,
-     * Vector4, Vector4, Vector4)}. The ambient, specular, and emissive colors still
-     * affect the final rendering, but the diffuse color will be taken from this
-     * attribute.
+     * This will replace the diffuse color that is specified in {@link
+     * #setMaterial(Vector4, Vector4, Vector4, Vector4)} or {@link
+     * #setMaterialDiffuse(com.ferox.math.Vector4)}. The ambient, specular, and emissive
+     * colors still affect the final rendering, but the diffuse color will be taken from
+     * this attribute.
      * <p/>
      * This updates the currently bound color attribute. The bound attribute will remain
      * unchanged after rendering until this method is called again. If a null attribute is
      *
      * @param colors The VertexAttribute holding the color vector data
      *
-     * @throws IllegalArgumentException if colors element size is not 3 or 4, or if its
-     *                                  type is not FLOAT
+     * @throws IllegalArgumentException if colors element size is not 3 or 4, or if it
+     *                                  does not hold decimal data
      */
     public void setColors(VertexAttribute colors);
 
     /**
      * <p/>
      * Set the VertexAttribute that is used as a source of texture coordinates on the
-     * texture unit, <var>tex</var> when {@link #render(PolygonType, int, int)} or {@link
-     * #render(PolygonType, com.ferox.renderer.geom.VertexBufferObject, int)} is invoked.
-     * The attribute element size can be any value between 1 and 4. If the element size of
-     * the attribute doesn't meet the expected coordinate size of the bound texture, a
-     * default is used for the missing components. The 2nd and 3rd components default to 0
-     * and the 4th defaults to 1. The attribute type must be FLOAT.
+     * texture unit, <var>tex</var> when {@link #render(PolygonType, int, int)}  is
+     * invoked. The attribute element size can be any value between 1 and 4. If the
+     * element size of the attribute doesn't meet the expected coordinate size of the
+     * bound texture, a default is used for the missing components. The 2nd and 3rd
+     * components default to 0 and the 4th defaults to 1. The vertex buffer's data type
+     * must hold decimal data.
      * <p/>
      * This updates the currently bound texture coordinate attribute for the given texture
      * unit. The bound attribute will remain unchanged after rendering until this method
      * attribute can be unbound from the texture unit if a null VertexAttribute is
      * provided.
      * <p/>
-     * Every texture unit starst with no attribute bound.
+     * Every texture unit initially has no attribute bound.
      *
      * @param tex       The texture unit to bind <var>texCoords</var> to
      * @param texCoords The VertexAttribute holding the texture coordinate data and access
      *                  information
      *
-     * @throws IllegalArgumentException  if texCoords' data type is not FLOAT
+     * @throws IllegalArgumentException  if texCoords' data type is not a decimal type
      * @throws IndexOutOfBoundsException if the hardware does not support a texture at the
      *                                   provided index, or if tex is less than 0
      */

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

  * {@link Surface surfaces}, which store the final render outputs, and provides {@link
  * HardwareAccessLayer} and {@link Context} implementations that allow actual use of
  * Renderers and Resources. A Framework acts as an advanced task execution service that
- * queues up {@link Task tasks} to run on internal threads that can communicate with
+ * queues up {@link Task tasks} to run on an internal thread that can communicate with
  * low-level graphics drivers.
  * <p/>
- * It is not defined how many threads are used internally to execute tasks. Given the
- * state of current desktop hardware and OSes (aka Windows), it will likely use a single
- * thread. This is reasonably because there is generally only one GPU.
+ * Framework implementations are thread safe so that a single Framework instance can be
+ * used from multiple threads. Generally, a single Framework should active at a time.
+ * Renderers, Contexts and HardwareAccessLayers are not thread safe and it is only valid
+ * to use them within the scope of the task execution on the framework thread.
  * <p/>
- * Framework implementations must be thread safe so that a single Framework instance can
- * be used from multiple threads. The thread safety of Renderers, Contexts and
- * HardwareAccessLayers is not defined because their exposure is carefully controlled by
- * task invocation.
+ * Resources are constructed from the Framework using the builder pattern. Framework
+ * exposes builder creation methods for the currently supported resource types. The
+ * builders perform little to no validation until the actual {@code build()} method is
+ * invoked. At this point, synchronization is done with the framework thread to construct
+ * the resource on the GPU. Invoking builders on the actual framework thread can avoid
+ * this blocking because they will run immediately.
  * <p/>
- * An important part of a Framework implementation is resource management. All Frameworks
- * are required to automatically clean up internal resource data when a {@link Resource}
- * is garbage collected.
+ * If a particular resource or resource configuration is unsupported or fails to be
+ * created (such as a compilation error in the shader, or out of memory when allocating a
+ * buffer) a ResourceException is thrown at build time. Changing the state of the builder
+ * from multiple threads is not safe, but it is safe to mutate a builder's configuration
+ * after invoking build() to configure a second resource.
  * <p/>
- * Most low-level graphics languages have the concept of a context, where a thread needs
- * an active context to be able to communicate with the graphics hardware. The contexts
- * provided by a Framework are on a much higher level but have a similar scope of
- * usability; they only function on threads managed by the Framework that control the
- * low-level driver access.
+ * Resources created by one Framework cannot be used with any other Framework instance and
+ * will be automatically destroyed when the framework is destroyed. All non-destroyed
+ * surfaces will be destroyed when the framework is destroyed.
  *
  * @author Michael Ludwig
  */
 public interface Framework extends Destructible {
     /**
-     * Return an array of available DisplayModes that can be used when creating fullscreen
-     * surfaces with {@link #createSurface(OnscreenSurfaceOptions)}. The returned array
-     * can be modified because a defensive copy is returned.
-     *
-     * @return All available display modes on the system
-     */
-    public DisplayMode[] getAvailableDisplayModes();
-
-    /**
      * Return the DisplayMode representing the default display mode selected when the
      * surface is no longer fullscreen. This will be the original display mode selected by
      * the user before they started the application.
      */
     public DisplayMode getDefaultDisplayMode();
 
-    // FIXME these should be defensive copies, and are ordered in increasing bit size
-    public int[] getAvailableDepthBufferSizes();
-
-    public int[] getAvailableStencilBufferSizes();
-
-    public int[] getAvailableSamples();
-
     /**
      * <p/>
      * Return the current exclusive fullscreen surface. There can only be one fullscreen
      */
     public OnscreenSurface getFullscreenSurface();
 
-    // FIXME get rid of the clauses saying frameworks can modify the options to create
-    // a successful surface. It's all or nothing at this point, makes the implementation
-    // easier and fallback code is easier because the application knows what each failure
-    // was, instead of having to dig into the returned surface and check what changed
-
     /**
      * <p/>
-     * Create a OnscreenSurface with the given options. These parameters are requests to
-     * the underlying Framework, which will try its best to follow them. When the window
-     * surface is returned, it will be visible and on screen.
+     * Create a OnscreenSurface with the given options. If the Framework cannot create a
+     * surface satisfying the options an exception is thrown. To prevent this from
+     * occurring, use display modes, depth buffer sizes, stencil buffer sizes, and sample
+     * counts that were reported by {@link #getCapabilities()}. When the window surface is
+     * returned, it will be visible and on screen.
      * <p/>
-     * If any of the options have unsupported values, the Framework may change them to
-     * successfully create a surface.
-     * <p/>
-     * If there is already a fullscreen surface and <var>options</var> would create a new
-     * fullscreen surface, an exception is thrown. It is possible to have standard
-     * windowed surfaces and fullscreen surface, although the windowed surfaces will be
-     * hidden until the fullscreen surface is destroyed.
+     * If there is already a fullscreen surface  an exception is thrown.
      * <p/>
      * Some Frameworks may not support multiple OnscreenSurfaces depending on their
      * windowing libraries.
 
     /**
      * <p/>
-     * Create a TextureSurface that can be used to render into textures. The Framework
-     * will create new textures that can be retrieved by calling the returned surface's
-     * {@link TextureSurface#getColorBuffer(int)} and {@link TextureSurface#getDepthBuffer()}.
-     * The size and texture format of the {@link Texture textures} used for the
-     * TextureSurface are determined by the provided <var>options</var>.
+     * Create a TextureSurface that can be used to render into textures. All created
+     * texture surfaces can have up to the maximum number of color targets at a time, and
+     * their configured render targets are fluid. They can be changed by invoking {@link
+     * HardwareAccessLayer#setActiveSurface(TextureSurface, com.ferox.renderer.Sampler.RenderTarget[],
+     * com.ferox.renderer.Sampler.RenderTarget)} and related methods.
      * <p/>
-     * If <var>options</var> is unsupported, the Framework is permitted to choose options
-     * that allow it to create a valid TextureSurface. This includes changing the format
-     * or dimensions to fit within hardware limits.
+     * If render targets are provided in the options, they will represent the initial
+     * target configuration of the surface. Regardless of when the targets are specified,
+     * targets must have the same 2D dimensions as the created texture surface and all
+     * color targets must have the same data and base format and mipmap configuration.
      *
      * @param options The requested options for configuring the created surface
      *
 
     /**
      * <p/>
-     * Queue the given Task to be run as soon as possible by internal threads managed by
-     * the Framework. The Framework must support receiving tasks from multiple threads
-     * safely. Ordering of queued tasks across multiple threads depends on the scheduling
-     * of threads. Tasks queued from the same thread will be invoked in the order
-     * received.
+     * Run the given Task on the internal threads managed by the Framework. The Framework
+     * must support receiving tasks from multiple threads safely. Ordering of tasks from
+     * across multiple threads will be queued arbitrarily based on thread scheduling.
+     * Tasks invoked directly on the internal thread will be run immediately and the
+     * returned future will have already completed.
      * <p/>
-     * If the Framework is destroyed before a Task has started, its returned Future will
+     * If the Framework is destroyed before a Task has started, the returned Future will
      * be canceled. Calls to this method are ignored if the Framework is already
      * destroyed.
      *
      *
      * @throws NullPointerException if the task is null
      */
-    public <T> Future<T> queue(Task<T> task);
-
-    /**
-     * <p/>
-     * Convenience method to queue a Task that will dispose the given resource by calling
-     * {@link Context#dispose(Resource)}. It is not recommended to use this method if
-     * resources are being updated and disposed of with custom Tasks.
-     * <p/>
-     * This method does nothing if the Framework has been destroyed. Since the Framework's
-     * destruction disposes any resource data anyway, this is not a problem. This will
-     * unblock and return if the Framework is destroyed while waiting for the dispose to
-     * complete.
-     *
-     * @param resource The resource to dispose
-     *
-     * @throws NullPointerException if resource is null
-     */
-    public void destroy(Resource resource);
+    public <T> Future<T> invoke(Task<T> task);
 
     /**
      * <p/>
      * Convenience method to queue a Task that will flush the provided surface. If the
-     * flush is not being performed by already queued tasks, this is needed to ensure that
-     * any rendering is made visible to the surface. If the surface is a TextureSurface
-     * with multiple render targets, only its default active layer is flushed. If finer
-     * control is needed, a custom task will need to be queued instead.
+     * flush is not being performed by queued tasks, this is needed to ensure that any
+     * rendering is made visible to the surface. If the surface is a TextureSurface, it is
+     * flushed to its last used render target configuration. If finer control is needed, a
+     * custom task will need to be queued instead.
      * <p/>
      * An exception is thrown if the surface is not owned by the Framework. If the
      * provided surface has been destroyed, this method will do nothing. It is not best
      * practice to queue or use surfaces that have been destroyed, but this behavior is
      * safe in order to play nicely with onscreen surfaces that can be closed by the user
      * at any time. If the Framework is destroyed, this will do nothing and return
-     * immediately. This will also return as a soon as a Framework is destroyed if this
-     * was actively blocking.
+     * immediately.
      *
      * @param surface The surface to flush
      *
      */
     public void sync();
 
+    /**
+     * @return A new builder for creating a {@link VertexBuffer}
+     */
     public VertexBufferBuilder newVertexBuffer();
 
+    /**
+     * @return A new builder for creating a {@link ElementBuffer}
+     */
     public ElementBufferBuilder newElementBuffer();
 
+    /**
+     * @return A new builder for creating a {@link Shader}
+     */
     public ShaderBuilder newShader();
 
+    /**
+     * @return A new builder for creating a {@link Texture1D}
+     */
     public Texture1DBuilder newTexture1D();
 
+    /**
+     * @return A new builder for creating a {@link Texture2D}
+     */
     public Texture2DBuilder newTexture2D();
 
+    /**
+     * @return A new builder for creating a {@link TextureCubeMap}
+     */
     public TextureCubeMapBuilder newTextureCubeMap();
 
+    /**
+     * @return A new builder for creating a {@link Texture3D}
+     */
     public Texture3DBuilder newTexture3D();
 
+    /**
+     * @return A new builder for creating a {@link Texture1DArray}
+     */
     public Texture1DArrayBuilder newTexture1DArray();
 
+    /**
+     * @return A new builder for creating a {@link Texture2DArray}
+     */
     public Texture2DArrayBuilder newTexture2DArray();
 
+    /**
+     * @return A new builder for creating a {@link DepthMap2D}
+     */
     public DepthMap2DBuilder newDepthMap2D();
 
+    /**
+     * @return A new builder for creating a {@link DepthCubeMap}
+     */
     public DepthCubeMapBuilder newDepthCubeMap();
 
     /**
      * Get the capabilities of this Framework. This is allowed to return null after the
      * Framework is destroyed although Frameworks might not behave this way.
      *
-     * @return The RenderCapabilities for this Framework
+     * @return The Capabilities for this Framework
      */
-    public RenderCapabilities getCapabilities();
+    public Capabilities getCapabilities();
 }

ferox-renderer/ferox-renderer-api/src/main/java/com/ferox/renderer/HardwareAccessLayer.java

 
 /**
  * The HardwareAccessLayer is the direct interface Tasks use to access graphics hardware.
- * It has two broad capabilities: working with Resource's and the hardware layer data
- * needed to use them, and rendering into Surfaces. Each Task that is run by a Framework
- * is provided a HardwareAccessLayer to utilize in whatever manner they see fit. The
+ * Each Task that is run by a Framework is provided a HardwareAccessLayer to then activate
+ * surfaces and use the returned contexts to access the approprate renderers. The
  * HardwareAccessLayer is tied to the thread executing the Task so it (and the related
  * {@link Context}) must not be held onto outside of the Task's execution period.
  * <p/>
- * <p/>
- * Resources can be manually updated and disposed of by using the HardwareAccessLayer.
- * Because the hardware level data for a Resource is shared across all threads and
- * surfaces in a Framework, it does not matter which task group or HardwareAccessLayer
- * instance is used to perform an update or dispose, the change will by Framework-wide.
  * Surfaces can be rendered into by first activating them with setActiveSurface(), and
  * then using one of the Renderer's from the Context associated with the active surface.
  * In order for a user to see the actual rendered content, the surface must be {@link
      * Set the active Surface for rendering when using this hardware access layer. A
      * Surface must be active in order to use any Renderers (which are provided by the
      * returned Context). This may be called multiple times by the same Task, although
-     * only one Surface will be active for the task at a given time. A Surface can only be
-     * active within a single task as well, but this is only relevant if the Framework
-     * supports can process tasks from multiple threads.
+     * only one Surface will be active for the task at a given time.
      * <p/>
      * The returned Context is only valid while the specified surface is active. If this
      * is called again with any surface (including this one), the old Context must be
      * discarded and the new Context should be used.
      * <p/>
-     * The update, dispose and reset operations provided by this access layer can be used
-     * whether or not a surface is active and their high-level behavior does not change if
-     * a Surface is active. Resource operations can be interleaved with rendering
-     * operations.
-     * <p/>
-     * Calling this method with a null surface is allowed. It deactivates any current
-     * surface, allowing that surface to be activated by other Tasks. A null surface will
-     * return a null context. Using a null surface effectively restores the hardware
-     * access layer to its initial state when the Task began executing.
+     * Calling this method with a null surface is allowed. A null surface will return a
+     * null context. Using a null surface effectively restores the hardware access layer
+     * to its initial state when the Task began executing.
      * <p/>
      * If the provided Surface is a TextureSurface, the surface will be activated using
-     * its default activate layer or default active depth plane depending on if it has a
-     * cube map or 3D texture. Other texture types do not have multiple layers to select
-     * so it does not matter.
+     * its last render target configuration. Its render target configuration was either
+     * determined by the options specified when it was created, or by a call to one of the
+     * setActiveSurface() variants that take render targets.
      * <p/>
      * If the surface has its {@link Surface#destroy()} method called before it is
      * activated, a null Context is returned. A Surface cannot be destroyed until it has
-     * been deactivated, in which case the caller will block. The only exception to this
-     * is if the Thread running the Task calls destroy. In this case, the Surface is
-     * deactivated automatically and then destroyed.
+     * been deactivated, in which case the destruction action will wait until it's
+     * released. The only exception to this is if the Thread running the Task calls
+     * destroy. In this case, the Surface is deactivated automatically, destroyed, and its
+     * context must be discarded.
      *
      * @param surface The Surface to activate, or null to deactivate the current surface
      *
      * @return A Context to use for the activation lifetime of the given Surface, or null
      *         if surface was null was or destroyed
+     *
+     * @throws IllegalArgumentException if the surface was created by another Framework
      */
     public Context setActiveSurface(Surface surface);
 
+    /**
+     * Activate the given TextureSurface and update its color target configuration to
+     * render into the single color target. This is equivalent to calling {@code
+     * setActiveSurface(surface, singleColorBuffer, null)}.
+     *
+     * @param surface           The texture surface to activate
+     * @param singleColorBuffer The new color render target
+     *
+     * @return A context to use, or null if the surface was destroyed
+     *
+     * @throws IllegalArgumentException if the surface was created by another Framework,
+     *                                  or if the dimensions of the surface and target
+     *                                  don't match
+     * @see #setActiveSurface(TextureSurface, com.ferox.renderer.Sampler.RenderTarget[],
+     *      com.ferox.renderer.Sampler.RenderTarget)
+     */
+    public Context setActiveSurface(TextureSurface surface,
+                                    Sampler.RenderTarget singleColorBuffer);
 
+    /**
+     * Activate the given TextureSurface and update its color target configuration to
+     * render into the single color target. Update the depth target to {@code
+     * depthBuffer}. This is equivalent to calling:
+     * <pre>
+     *     RenderTarget targets = new RenderTarget[1];
+     *     targets[0] = singleColorBuffer;
+     *     setActiveSurface(surface, targets, depthBuffer):
+     * </pre>
+     *
+     * @param surface           The texture surface to activate
+     * @param singleColorBuffer The new color render target
+     * @param depthBuffer       The new depth/stencil target
+     *
+     * @return A context to use, or null if the surface was destroyed
+     *
+     * @throws IllegalArgumentException if the surface was created by another Framework,
+     *                                  if the dimensions of the surface and target don't
+     *                                  match, or if the surface has a depth render buffer
+     *                                  but the depth target is non-null
+     * @see #setActiveSurface(TextureSurface, com.ferox.renderer.Sampler.RenderTarget[],
+     *      com.ferox.renderer.Sampler.RenderTarget)
+     */
     public Context setActiveSurface(TextureSurface surface,
                                     Sampler.RenderTarget singleColorBuffer,
                                     Sampler.RenderTarget depthBuffer);
 
-    public Context setActiveSurface(TextureSurface surface,
-                                    Sampler.RenderTarget singleColorBuffer);
-
+    /**
+     * Activate the given TextureSurface and update its color target configuration to
+     * render into multiple color targets. If the length of {@code colorBuffers} is less
+     * than the number of supported targets, the remaining targets are cleared. An
+     * exception is thrown if more color targets are provided than are supported. If there
+     * are no color targets, then rendering will proceed without a color buffer. This can
+     * be useful if only the depth information is required in a particular pass.
+     * <p/>
+     * OpenGL defines potentially many color buffers that can be rendered into
+     * simultaneously. Shaders must be configured to map from their declared output
+     * variables to the color buffers. Each color buffer is indexed starting at 0. The
+     * index of each render target in the {@code colorBuffers} array is the same color
+     * buffer index that must line up with the intended shader's configuration or your
+     * rendering results will not be correct.
+     * <p/>
+     * The depth/stencil target will be bound to {@code depthBuffer}. If the texture
+     * surface was created to have a depth renderbuffer, {@code depthBuffer} must be null.
+     * If {@code depthBuffer} is null and there is no renderbuffer then rendering will be
+     * performed without the depth test. The same goes for the stencil test.
+     * <p/>
+     * The dimensions of the texture surface and textures providing the render targets
+     * must be equal.
+     *
+     * @param surface      The texture surface to activate
+     * @param colorBuffers The new color render targets
+     * @param depthBuffer  The new depth/stencil target
+     *
+     * @return A context to use, or null if the surface was destroyed
+     *
+     * @throws IllegalArgumentException if the surface was created by another Framework,
+     *                                  if the dimensions of the surface and target don't
+     *                                  match, if the surface has a depth render buffer
+     *                                  but the depth target is non-null, or if too many
+     *                                  color targets are provided
+     * @see #setActiveSurface(Surface)
+     */
     public Context setActiveSurface(TextureSurface surface,
                                     Sampler.RenderTarget[] colorBuffers,
                                     Sampler.RenderTarget depthBuffer);
      * @return The current context
      */
     public Context getCurrentContext();
+
+    /**
+     * Refresh the dynamic state of the resource, performing the same actions as {@link
+     * com.ferox.renderer.Resource#refresh()} except the refresh is performed immediately
+     * on the calling thread (i.e. the internal framework thread). The resource is
+     * guaranteed refreshed after this returns and avoids the cost of allocating a task or
+     * future object.
+     * <p/>
+     * This is the preferred method for refreshing resources when performance is
+     * critical.
+     *
+     * @param resource The resource to update
+     *
+     * @throws NullPointerException     if the resource is null
+     * @throws IllegalArgumentException if the resource was created by another Framework
+     */
+    public void refresh(Resource resource);
+
+    /**
+     * Manually destroy the resource. This performs the same actions as {@link
+     * com.ferox.renderer.Resource#destroy()} except the destruction of the internal GPU
+     * resources is performed immediately before the method returns. This does nothing if
+     * the resource has already been destroyed by any means.
+     * <p/>
+     * This is the preferred method for destroying resources when performance and exact
+     * control over timing is necessary. Like {@link #refresh(Resource)} it avoids the
+     * cost of allocating and queuing a task.
+     *
+     * @param resource The resource to destroy
+     *