Commits

Michael Ludwig  committed 83b4e77

Repair resource handles and abstract driver implementations.

  • Participants
  • Parent commits 0b0e9a5

Comments (0)

Files changed (6)

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/drivers/AbstractGlslShaderResourceDriver.java

 
 import com.ferox.renderer.impl.OpenGLContext;
 import com.ferox.renderer.impl.ResourceDriver;
-import com.ferox.renderer.impl.ResourceHandle;
+import com.ferox.renderer.impl.UpdateResourceException;
 import com.ferox.resource.GlslShader;
 import com.ferox.resource.GlslShader.ShaderType;
-import com.ferox.resource.Resource.Status;
+import com.ferox.resource.Resource;
 
 /**
  * Abstract implementation of a ResourceDriver for GlslShaders. This implements
  * 
  * @author Michael Ludwig
  */
-public abstract class AbstractGlslShaderResourceDriver implements ResourceDriver<GlslShader> {
+public abstract class AbstractGlslShaderResourceDriver implements ResourceDriver {
     @Override
-    public ResourceHandle update(OpenGLContext context, GlslShader shader, ResourceHandle handle) {
+    public Object init(Resource resource) {
+        return new GlslShaderHandle();
+    }
+    
+    @Override
+    public String update(OpenGLContext context, Resource resource, Object handle) throws UpdateResourceException {
+        GlslShader shader = (GlslShader) resource;
+        GlslShaderHandle h = (GlslShaderHandle) handle;
         EnumSet<ShaderType> supported = context.getRenderCapabilities().getSupportedShaderTypes();
 
-        if (handle == null) {
-            // Create a new shader program, and check for GLSL support
-            if (supported.isEmpty() || context.getRenderCapabilities().getGlslVersion() == null) {
-                handle = new ResourceHandle(shader);
-                handle.setStatus(Status.UNSUPPORTED);
-                handle.setStatusMessage("GLSL is not supported on current hardware");
-                return handle;
-            }
-            
-            // GLSL is supported to some extent at least so create a new program handle
-            handle = new GlslShaderHandle(shader, glCreateProgram(context));
+        if (supported.isEmpty() || context.getRenderCapabilities().getGlslVersion() == null) {
+            throw new UpdateResourceException("GLSL is not supported on current hardware");
         }
         
-        if (handle instanceof GlslShaderHandle) {
-            GlslShaderHandle h = (GlslShaderHandle) handle;
+        
+        if (h.programID <= 0) {
+            // Create a new shader program id
+            h.programID = glCreateProgram(context);
+        }
+        
+        // Loop over all shaders and see if they've been changed
+        List<String> problems = null;
+        boolean needsRelink = false;
 
-            // Loop over all shaders and see if they've been changed
-            List<String> problems = null;
-            boolean needsRelink = false;
-            
-            ShaderType[] values = ShaderType.values();
-            for (int i = 0; i < values.length; i++) {
-                ShaderType type = values[i];
-                
-                String oldShaderSource = h.shaderSource.get(type);
-                String newShaderSource = shader.getShader(type);
-                
-                if (areSourcesDifferent(oldShaderSource, newShaderSource)) {
-                    if (supported.contains(type)) {
-                        Integer shaderId = h.shaders.get(type);
-                        if (newShaderSource == null && shaderId != null) {
-                            // Remove the old shader
-                            glDetachShader(context, h.programID, shaderId);
-                            glDeleteShader(context, shaderId);
+        ShaderType[] values = ShaderType.values();
+        for (int i = 0; i < values.length; i++) {
+            ShaderType type = values[i];
+
+            String oldShaderSource = h.shaderSource.get(type);
+            String newShaderSource = shader.getShader(type);
+
+            if (areSourcesDifferent(oldShaderSource, newShaderSource)) {
+                if (supported.contains(type)) {
+                    Integer shaderId = h.shaders.get(type);
+                    if (newShaderSource == null && shaderId != null) {
+                        // Remove the old shader
+                        glDetachShader(context, h.programID, shaderId);
+                        glDeleteShader(context, shaderId);
+                    }
+
+                    if (newShaderSource != null) {
+                        // Compile and attach new version
+                        if (shaderId == null) {
+                            shaderId = glCreateShader(context, type);
+                            glAttachShader(context, h.programID, shaderId);
+                            h.shaders.put(type, shaderId);
                         }
 
-                        if (newShaderSource != null) {
-                            // Compile and attach new version
-                            if (shaderId == null) {
-                                shaderId = glCreateShader(context, type);
-                                glAttachShader(context, h.programID, shaderId);
-                                h.shaders.put(type, shaderId);
-                            }
+                        String errorLog = glCompileShader(context, shaderId, newShaderSource);
+                        if (errorLog != null) {
+                            if (problems == null)
+                                problems = new ArrayList<String>();
+                            problems.add("Error compiling " + type + " shader: " + errorLog);
+                        } else {
+                            // No error so update the shader source map so future updates
+                            // don't do extra work
+                            h.shaderSource.put(type, newShaderSource);
+                        }
+                    } else {
+                        // No more shader for this type, clean type from the map
+                        h.shaders.remove(type);
+                        h.shaderSource.remove(type);
+                    }
 
-                            String errorLog = glCompileShader(context, shaderId, newShaderSource);
-                            if (errorLog != null) {
-                                if (problems == null)
-                                    problems = new ArrayList<String>();
-                                problems.add("Error compiling " + type + " shader: " + errorLog);
-                            } else {
-                                // No error so update the shader source map so future updates
-                                // don't do extra work
-                                h.shaderSource.put(type, newShaderSource);
-                            }
-                        } else {
-                            // No more shader for this type, clean type from the map
-                            h.shaders.remove(type);
-                            h.shaderSource.remove(type);
-                        }
-
-                        // Record that we've changed the program
-                        needsRelink = true;
-                    } else {
-                        if (problems == null)
-                            problems = new ArrayList<String>();
-                        problems.add("Hardware does not support shader type: " + type);
-                        needsRelink = true; // set to true to fall into the error handling code
-                    }
+                    // Record that we've changed the program
+                    needsRelink = true;
+                } else {
+                    if (problems == null)
+                        problems = new ArrayList<String>();
+                    problems.add("Hardware does not support shader type: " + type);
+                    needsRelink = true; // set to true to fall into the error handling code
                 }
             }
+        }
             
-            // Update the program if we changed the shaders at all
-            if (needsRelink) {
-                h.attributes.clear();
-                h.uniforms.clear();
-                
-                // Check for errors with compiling of the shaders
-                if (problems != null) {
-                    h.setStatus(Status.ERROR);
-                    h.setStatusMessage(problems.toString());
-                    return h;
-                }
-                
-                // Link the program
-                String errorLog = glLinkProgram(context, h.programID);
-                if (errorLog != null) {
-                    // Program linking failed
-                    h.setStatus(Status.ERROR);
-                    h.setStatusMessage(errorLog);
-                    return h;
-                }
-                
-                // No failures, so update the uniforms and attrs
-                updateUniforms(context, h);
-                updateAttributes(context, h);
-                
-                h.setStatus(Status.READY);
-                h.setStatusMessage("");
+        // Update the program if we changed the shaders at all
+        if (needsRelink) {
+            h.attributes.clear();
+            h.uniforms.clear();
+
+            // Check for errors with compiling of the shaders
+            if (problems != null) {
+                throw new UpdateResourceException(problems.toString());
             }
+
+            // Link the program
+            String errorLog = glLinkProgram(context, h.programID);
+            if (errorLog != null) {
+                // Program linking failed
+                throw new UpdateResourceException(errorLog);
+            }
+
+            // No failures, so update the uniforms and attrs
+            updateUniforms(context, h);
+            updateAttributes(context, h);
         }
         
         // Made it this far, the handle has been configured correctly
-        return handle;
+        return "";
     }
     
     @Override
-    public void reset(GlslShader shader, ResourceHandle handle) {
+    public void reset(Object handle) {
         if (handle instanceof GlslShaderHandle) {
             GlslShaderHandle h = (GlslShaderHandle) handle;
             h.shaderSource.clear();
     }
 
     @Override
-    public void dispose(OpenGLContext context, ResourceHandle handle) {
+    public void dispose(OpenGLContext context, Object handle) {
         if (handle instanceof GlslShaderHandle) {
             GlslShaderHandle h = (GlslShaderHandle) handle;
             

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/drivers/AbstractTextureResourceDriver.java

 import com.ferox.renderer.impl.BufferUtil;
 import com.ferox.renderer.impl.OpenGLContext;
 import com.ferox.renderer.impl.ResourceDriver;
-import com.ferox.renderer.impl.ResourceHandle;
+import com.ferox.renderer.impl.UpdateResourceException;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.Mipmap;
 import com.ferox.resource.MipmapRegion;
-import com.ferox.resource.Resource.Status;
+import com.ferox.resource.Resource;
 import com.ferox.resource.Texture;
 import com.ferox.resource.TextureFormat;
 
  * 
  * @author Michael Ludwig
  */
-public abstract class AbstractTextureResourceDriver implements ResourceDriver<Texture> {
+public abstract class AbstractTextureResourceDriver implements ResourceDriver {
     @Override
     public Class<Texture> getResourceType() {
         return Texture.class;
     }
     
     @Override
-    public void reset(Texture tex, ResourceHandle handle) {
+    public void reset(Object handle) {
         if (handle instanceof TextureHandle) {
             TextureHandle h = (TextureHandle) handle;
             
     }
     
     @Override
-    public void dispose(OpenGLContext context, ResourceHandle handle) {
+    public void dispose(OpenGLContext context, Object handle) {
         if (handle instanceof TextureHandle)
             glDeleteTexture(context, (TextureHandle) handle);
     }
 
     @Override
-    public ResourceHandle update(OpenGLContext context, Texture tex, ResourceHandle handle) {
-        if (handle == null) {
-            if (!context.getRenderCapabilities().getSupportedTextureTargets().contains(tex.getTarget())) {
-                handle = new ResourceHandle(tex);
-                handle.setStatus(Status.UNSUPPORTED);
-                handle.setStatusMessage("Texture target, " + tex.getTarget() + ", is not supported");
-            } else {
-                handle = new TextureHandle(tex);
-            }
+    public String update(OpenGLContext context, Resource res, Object handle) throws UpdateResourceException {
+        Texture tex = (Texture) res;
+        TextureHandle h = (TextureHandle) handle;
+        
+        if (!context.getRenderCapabilities().getSupportedTextureTargets().contains(tex.getTarget())) {
+            throw new UpdateResourceException("Texture target " + tex.getTarget() + " is unsupported");
         }
         
-        if (handle instanceof TextureHandle) {
-            TextureHandle h = (TextureHandle) handle;
-            boolean isBound = false;
+        boolean isBound = false;
             
-            // Check for errors in dimensions, format, type, etc.
-            if (!validateTexture(context, tex, h))
-                return h;
+        // Check for errors in dimensions, format, type, etc.
+        validateTexture(context, tex, h);
             
-            // Check for (and possibly update) texture parameters
-            if (haveParametersChanged(tex, h)) {
+        // Check for (and possibly update) texture parameters
+        if (haveParametersChanged(tex, h)) {
+            glBindTexture(context, h);
+            isBound = true;
+
+            glTextureParameters(context, tex, h);
+        }
+            
+        if (tex.getChangeQueue().isVersionStale(h.lastSyncedVersion)) {
+            if (!isBound) {
                 glBindTexture(context, h);
                 isBound = true;
+            }
+                
+            boolean isMissingChanges = tex.getChangeQueue().hasLostChanges(h.lastSyncedVersion);
+                
+            // organize all changes by layer and mipmap level
+            @SuppressWarnings("unchecked")
+            Map<Integer, List<MipmapRegion>>[] changes = new Map[h.lastSyncedKeys.length];
+            for (MipmapRegion edit: tex.getChangeQueue().getChangesSince(h.lastSyncedVersion)) {
+                int layer = edit.getLayer();
+                int mipmap = edit.getMipmapLevel();
 
-                glTextureParameters(context, tex, h);
+                if (layer >= changes.length)
+                    continue; // user created a bad mipmap region
+
+                if (changes[layer] == null)
+                    changes[layer] = new HashMap<Integer, List<MipmapRegion>>();
+                if (changes[layer].get(mipmap) == null)
+                    changes[layer].put(mipmap, new ArrayList<MipmapRegion>());
+                changes[layer].get(mipmap).add(edit);
             }
+                
+            // update type/format/isMipmapped based on potentially new sets of mipmaps
+            TextureFormat format = tex.getFormat();
+            if (!context.getRenderCapabilities().getUnclampedFloatTextureSupport()) {
+                // our best bet is to switch to clamped float formatting
+                switch(format) {
+                case R_FLOAT:
+                    format = TextureFormat.R;
+                    break;
+                case RG_FLOAT:
+                    format = TextureFormat.RG;
+                    break;
+                case RGB_FLOAT:
+                    format = TextureFormat.RGB;
+                    break;
+                case DEPTH_FLOAT:
+                    format = TextureFormat.DEPTH;
+                    break;
+                case RGBA_FLOAT:
+                    format = TextureFormat.RGBA;
+                    break;
+                }
+            }
+
+            h.format = format;
+            h.type = tex.getDataType();
+            h.isMipmapped = tex.getLayer(0).isMipmapped();
+                
+            for (int i = 0; i < h.lastSyncedKeys.length; i++) {
+                Mipmap mipmap = tex.getLayer(i);
+                int numMipmaps = mipmap.getNumMipmaps();
+                if (h.lastSyncedKeys[i] == null)
+                    h.lastSyncedKeys[i] = new Object[numMipmaps];
+                else if (numMipmaps != h.lastSyncedKeys[i].length)
+                    h.lastSyncedKeys[i] = Arrays.copyOf(h.lastSyncedKeys[i], numMipmaps);
+
+                for (int j = 0; j < numMipmaps; j++) {
+                    BufferData data = mipmap.getData(j);
+                    if (isMissingChanges || data.getKey() != h.lastSyncedKeys[i][j]) {
+                        // make sure a tex image gets allocated and that we push
+                        // all of the changes
+                        doTexImage(context, h, mipmap, i, j);
+                    } else if (h.format == TextureFormat.DEPTH || h.format.isCompressed()) {
+                        // depth/compressed textures don't seem to behave well with glTexSubImage
+                        if (changes[i] != null && changes[i].containsKey(j))
+                            doTexImage(context, h, mipmap, i, j);
+                    } else {
+                        // use glTexSubImage to process all mipmap regions
+                        List<MipmapRegion> toFlush = (changes[i] != null ? changes[i].get(j) : null);
+                        if (toFlush != null) {
+                            for (MipmapRegion rg: toFlush)
+                                doTexSubImage(context, h, mipmap, rg);
+                        }
+                    }
+
+                    h.lastSyncedKeys[i][j] = data.getKey();
+                }
+            }
+
+            h.lastSyncedVersion = tex.getChangeQueue().getVersion();
+        }
             
-            if (tex.getChangeQueue().isVersionStale(h.lastSyncedVersion)) {
-                if (isBound) {
-                    glBindTexture(context, h);
-                    isBound = true;
-                }
-                
-                boolean isMissingChanges = tex.getChangeQueue().hasLostChanges(h.lastSyncedVersion);
-                
-                // organize all changes by layer and mipmap level
-                @SuppressWarnings("unchecked")
-                Map<Integer, List<MipmapRegion>>[] changes = new Map[h.lastSyncedKeys.length];
-                for (MipmapRegion edit: tex.getChangeQueue().getChangesSince(h.lastSyncedVersion)) {
-                    int layer = edit.getLayer();
-                    int mipmap = edit.getMipmapLevel();
-                    
-                    if (layer >= changes.length)
-                        continue; // user created a bad mipmap region
-                    
-                    if (changes[layer] == null)
-                        changes[layer] = new HashMap<Integer, List<MipmapRegion>>();
-                    if (changes[layer].get(mipmap) == null)
-                        changes[layer].put(mipmap, new ArrayList<MipmapRegion>());
-                    changes[layer].get(mipmap).add(edit);
-                }
-                
-                // update type/format/isMipmapped based on potentially new sets of mipmaps
-                TextureFormat format = tex.getFormat();
-                if (!context.getRenderCapabilities().getUnclampedFloatTextureSupport()) {
-                    // our best bet is to switch to clamped float formatting
-                    switch(format) {
-                    case ALPHA_FLOAT:
-                        format = TextureFormat.ALPHA;
-                        break;
-                    case LUMINANCE_ALPHA_FLOAT:
-                        format = TextureFormat.LUMINANCE_ALPHA;
-                        break;
-                    case LUMINANCE_FLOAT:
-                        format = TextureFormat.LUMINANCE;
-                        break;
-                    case RGB_FLOAT:
-                        format = TextureFormat.RGB;
-                        break;
-                    case RGBA_FLOAT:
-                        format = TextureFormat.RGBA;
-                        break;
-                    }
-                }
-                
-                h.format = format;
-                h.type = tex.getDataType();
-                h.isMipmapped = tex.getLayer(0).isMipmapped();
-                
-                for (int i = 0; i < h.lastSyncedKeys.length; i++) {
-                    Mipmap mipmap = tex.getLayer(i);
-                    int numMipmaps = mipmap.getNumMipmaps();
-                    if (h.lastSyncedKeys[i] == null)
-                        h.lastSyncedKeys[i] = new Object[numMipmaps];
-                    else if (numMipmaps != h.lastSyncedKeys[i].length)
-                        h.lastSyncedKeys[i] = Arrays.copyOf(h.lastSyncedKeys[i], numMipmaps);
-                    
-                    for (int j = 0; j < numMipmaps; j++) {
-                        BufferData data = mipmap.getData(j);
-                        if (isMissingChanges || data.getKey() != h.lastSyncedKeys[i][j]) {
-                            // make sure a tex image gets allocated and that we push
-                            // all of the changes
-                            doTexImage(context, h, mipmap, i, j);
-                        } else if (h.format == TextureFormat.DEPTH || h.format.isCompressed()) {
-                            // depth/compressed textures don't seem to behave well with glTexSubImage
-                            if (changes[i] != null && changes[i].containsKey(j))
-                                doTexImage(context, h, mipmap, i, j);
-                        } else {
-                            // use glTexSubImage to process all mipmap regions
-                            List<MipmapRegion> toFlush = (changes[i] != null ? changes[i].get(j) : null);
-                            if (toFlush != null) {
-                                for (MipmapRegion rg: toFlush)
-                                    doTexSubImage(context, h, mipmap, rg);
-                            }
-                        }
-                        
-                        h.lastSyncedKeys[i][j] = data.getKey();
-                    }
-                }
-                
-                h.lastSyncedVersion = tex.getChangeQueue().getVersion();
-            }
+        if (isBound)
+            glRestoreTexture(context);
             
-            if (isBound)
-                glRestoreTexture(context);
-            
-            if (h.format != tex.getFormat())
-                h.setStatusMessage("TextureFormat changed from " + tex.getFormat() + " to " + h.format + " to meet hardware support");
-            else
-                h.setStatusMessage("");
-            h.setStatus(Status.READY);
-        }
-        
-        return handle;
+        if (h.format != tex.getFormat())
+            return "TextureFormat changed from " + tex.getFormat() + " to " + h.format + " to meet hardware support";
+        else
+            return "";
     }
 
     /**
      * @param handle
      * @return True if the texture can be updated
      */
-    protected boolean validateTexture(OpenGLContext context, Texture tex, TextureHandle handle) {
-        String errorMsg = null;
+    protected void validateTexture(OpenGLContext context, Texture tex, TextureHandle handle) throws UpdateResourceException {
         // error handling for textures that are owned by texture surfaces
         //  1. They cannot change size from what is reported by the surface
         //  2. They cannot change texture format or data type
         //  3. They cannot be mipmapped -> this might go away
         if (tex.getOwner() != null) {
             TextureSurface owner = tex.getOwner();
-            if (tex.getWidth() != owner.getWidth() || tex.getHeight() != owner.getHeight()
-                || tex.getDepth() != owner.getDepth())
-                errorMsg = "Cannot change dimensions of a Texture owned by a TextureSurface";
+            if (tex.getWidth() != owner.getWidth() || tex.getHeight() != owner.getHeight() || tex.getDepth() != owner.getDepth())
+                throw new UpdateResourceException("Cannot change dimensions of a Texture owned by a TextureSurface");
             else if (handle.format != null && tex.getFormat() != handle.format)
-                errorMsg = "Cannot change TextureFormat of a Texture owned by a TextureSurface";
+                throw new UpdateResourceException("Cannot change TextureFormat of a Texture owned by a TextureSurface");
             else if (handle.type != null && tex.getDataType() != handle.type)
-                errorMsg = "Cannot change DataType of a Texture owned by a TextureSurface";
+                throw new UpdateResourceException("Cannot change DataType of a Texture owned by a TextureSurface");
             else if (tex.getLayer(0).isMipmapped())
-                errorMsg = "Cannot use multiple mipmap levels with a Texture owned by a TextureSurface";
+                throw new UpdateResourceException("Cannot use multiple mipmap levels with a Texture owned by a TextureSurface");
         }
         
         RenderCapabilities caps = context.getRenderCapabilities();
-        if (errorMsg == null && !caps.getDepthTextureSupport() && tex.getFormat() == TextureFormat.DEPTH)
-            errorMsg = "Depth textures are not supported";
+        if (!caps.getDepthTextureSupport() && tex.getFormat() == TextureFormat.DEPTH)
+            throw new UpdateResourceException("Depth textures are not supported");
         
-        if (errorMsg == null && !caps.getNpotTextureSupport()) {
+        if (!caps.getNpotTextureSupport()) {
             if (tex.getWidth() != ceilPot(tex.getWidth()) || 
                 tex.getHeight() != ceilPot(tex.getHeight()) ||
                 tex.getDepth() != ceilPot(tex.getDepth()))
-                errorMsg = "Non-power of two textures are not supported";
+                throw new UpdateResourceException("Non-power of two textures are not supported");
         }
         
         int maxSize = 0;
             break;
         }
         
-        if (errorMsg == null && (tex.getWidth() > maxSize || 
-                                 tex.getHeight() > maxSize || 
-                                 tex.getDepth() > maxSize))
-            errorMsg = "Dimensions excede supported maximum of " + maxSize;
-        
-        if (errorMsg != null) {
-            handle.setStatus(Status.ERROR);
-            handle.setStatusMessage(errorMsg);
-            return false;
-        }
-        
-        return true;
+        if ((tex.getWidth() > maxSize || tex.getHeight() > maxSize || tex.getDepth() > maxSize))
+            throw new UpdateResourceException("Dimensions excede supported maximum of " + maxSize);
     }
 
     /**

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/drivers/AbstractVertexBufferObjectResourceDriver.java

 import com.ferox.renderer.impl.BufferUtil;
 import com.ferox.renderer.impl.OpenGLContext;
 import com.ferox.renderer.impl.ResourceDriver;
-import com.ferox.renderer.impl.ResourceHandle;
+import com.ferox.renderer.impl.UpdateResourceException;
 import com.ferox.resource.BufferData;
 import com.ferox.resource.BufferData.DataType;
 import com.ferox.resource.DataRange;
+import com.ferox.resource.Resource;
 import com.ferox.resource.VertexBufferObject;
-import com.ferox.resource.Resource.Status;
 import com.ferox.resource.VertexBufferObject.StorageMode;
 
 /**
  * 
  * @author Michael Ludwig
  */
-public abstract class AbstractVertexBufferObjectResourceDriver implements ResourceDriver<VertexBufferObject> {
-
+public abstract class AbstractVertexBufferObjectResourceDriver implements ResourceDriver {
     @Override
-    public ResourceHandle update(OpenGLContext context, VertexBufferObject res, ResourceHandle handle) {
-        if (handle == null)
-            handle = new VertexBufferObjectHandle(res);
+    public Object init(Resource resource) {
+        return new VertexBufferObjectHandle((VertexBufferObject) resource);
+    }
+    
+    @Override
+    public String update(OpenGLContext context, Resource res, Object handle) throws UpdateResourceException {
+        VertexBufferObject vbo = (VertexBufferObject) res;
         VertexBufferObjectHandle h = (VertexBufferObjectHandle) handle;
         
-        StorageMode newMode = (context.getRenderCapabilities().getVertexBufferSupport() ? res.getStorageMode() : StorageMode.IN_MEMORY);
+        StorageMode newMode = (context.getRenderCapabilities().getVertexBufferSupport() ? vbo.getStorageMode() : StorageMode.IN_MEMORY);
         
         boolean oldIsGPU = h.mode == StorageMode.GPU_DYNAMIC || h.mode == StorageMode.GPU_STATIC;
         boolean newIsGPU = newMode == StorageMode.GPU_DYNAMIC || newMode == StorageMode.GPU_STATIC;
         boolean storageModeChange = h.mode != newMode;
         
-        boolean isElementBuffer = res.getData().getDataType() != DataType.FLOAT;
+        boolean isElementBuffer = vbo.getData().getDataType() != DataType.FLOAT;
         
-        if (storageModeChange || res.getChangeQueue().isVersionStale(h.lastSyncedVersion)) {
+        if (storageModeChange || vbo.getChangeQueue().isVersionStale(h.lastSyncedVersion)) {
             if (storageModeChange) {
                 // Do some clean-up depending on the storage mode change
                 if (oldIsGPU && !newIsGPU)
                     glDeleteBuffer(context, h);
             }
             
-            if (storageModeChange || h.lastSyncedKey != res.getData().getKey() 
-                || res.getChangeQueue().hasLostChanges(h.lastSyncedVersion)) {
+            if (storageModeChange || h.lastSyncedKey != vbo.getData().getKey() 
+                || vbo.getChangeQueue().hasLostChanges(h.lastSyncedVersion)) {
                 // Must push the whole buffer
                 if (newIsGPU) {
                     // Operate on an actual VBO
-                    Buffer nioData = bufferAlloc(res.getData(), h.inmemoryBuffer);
+                    Buffer nioData = bufferAlloc(vbo.getData(), h.inmemoryBuffer);
                     
                     if (nioData != null || h.lastSyncedKey == null) {
                         if (isElementBuffer) {
                             glBindElementBuffer(context, h);
-                            glElementBufferData(context, nioData, res.getData().getDataType(), res.getData().getLength(), newMode);
+                            glElementBufferData(context, nioData, vbo.getData().getDataType(), vbo.getData().getLength(), newMode);
                             glRestoreElementBuffer(context);
                         } else {
                             glBindArrayBuffer(context, h);
-                            glArrayBufferData(context, nioData, res.getData().getDataType(), res.getData().getLength(), newMode);
+                            glArrayBufferData(context, nioData, vbo.getData().getDataType(), vbo.getData().getLength(), newMode);
                             glRestoreArrayBuffer(context);
                         }
                     } // no data and we've allocated data before, so don't change anything
                     
-                    h.inmemoryBuffer = (res.getStorageMode() == StorageMode.GPU_DYNAMIC ? nioData : null);
+                    h.inmemoryBuffer = (vbo.getStorageMode() == StorageMode.GPU_DYNAMIC ? nioData : null);
                 } else {
                     // Storage mode is IN_MEMORY so we want a buffer
-                    Buffer nioData = bufferAlloc(res.getData(), h.inmemoryBuffer);
+                    Buffer nioData = bufferAlloc(vbo.getData(), h.inmemoryBuffer);
                     if (nioData == null)
-                        nioData = BufferUtil.newBuffer(res.getData().getDataType(), res.getData().getLength());
+                        nioData = BufferUtil.newBuffer(vbo.getData().getDataType(), vbo.getData().getLength());
                     h.inmemoryBuffer = nioData;
                 }
                 
                 // Update properties in handle that could have changed because of doing a full push
-                h.dataType = res.getData().getDataType();
+                h.dataType = vbo.getData().getDataType();
                 h.mode = newMode;
-                h.length = res.getData().getLength();
-                h.lastSyncedKey = res.getData().getKey();
+                h.length = vbo.getData().getLength();
+                h.lastSyncedKey = vbo.getData().getKey();
             } else {
                 // Process all queued changes
-                if (res.getData().getArray() != null) {
+                if (vbo.getData().getArray() != null) {
                     // Can only update if we actually have data to sync
-                    List<DataRange> changes = res.getChangeQueue().getChangesSince(h.lastSyncedVersion);
+                    List<DataRange> changes = vbo.getChangeQueue().getChangesSince(h.lastSyncedVersion);
                     int numChanges = changes.size();
                     
                     if (h.mode != StorageMode.IN_MEMORY) {
                         
                         if (h.mode == StorageMode.IN_MEMORY) {
                             h.inmemoryBuffer.position(offset);
-                            bulkPut(res.getData(), offset, length, h.inmemoryBuffer);
+                            bulkPut(vbo.getData(), offset, length, h.inmemoryBuffer);
                             h.inmemoryBuffer.rewind();
                         } else {
                             Buffer nioData;
                                 nioData = h.inmemoryBuffer;
                                 nioData.limit(length).position(0);
                             } else {
-                                nioData = BufferUtil.newBuffer(res.getData().getDataType(), length);
+                                nioData = BufferUtil.newBuffer(vbo.getData().getDataType(), length);
                             }
                             nioData.rewind();
                             
                             if (isElementBuffer)
-                                glElementBufferSubData(context, nioData, res.getData().getDataType(), offset, length);
+                                glElementBufferSubData(context, nioData, vbo.getData().getDataType(), offset, length);
                             else
-                                glArrayBufferSubData(context, nioData, res.getData().getDataType(), offset, length);
+                                glArrayBufferSubData(context, nioData, vbo.getData().getDataType(), offset, length);
                         }
                     }
                 }
             }
             
-            h.lastSyncedVersion = res.getChangeQueue().getVersion();
+            h.lastSyncedVersion = vbo.getChangeQueue().getVersion();
             
-            if (h.mode != res.getStorageMode())
-                h.setStatusMessage("GPU storage modes are not supported, using IN_MEMORY instead");
-            h.setStatus(Status.READY);
+            if (h.mode != vbo.getStorageMode())
+                return "GPU storage modes are not supported, using IN_MEMORY instead";
         }
        
-        return handle;
+        return "";
     }
 
     @Override
-    public void reset(VertexBufferObject res, ResourceHandle handle) {
+    public void reset(Object handle) {
         if (handle instanceof VertexBufferObjectHandle) {
             VertexBufferObjectHandle h = (VertexBufferObjectHandle) handle;
             
     }
 
     @Override
-    public void dispose(OpenGLContext context, ResourceHandle handle) {
+    public void dispose(OpenGLContext context, Object handle) {
         if (handle instanceof VertexBufferObjectHandle) {
             VertexBufferObjectHandle h = (VertexBufferObjectHandle) handle;
             if (h.mode != StorageMode.IN_MEMORY)

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/drivers/GlslShaderHandle.java

 import java.util.HashMap;
 import java.util.Map;
 
-import com.ferox.renderer.impl.ResourceHandle;
-import com.ferox.resource.GlslShader;
 import com.ferox.resource.GlslShader.AttributeType;
 import com.ferox.resource.GlslShader.ShaderType;
 import com.ferox.resource.GlslUniform;
 
 /**
- * GlslShaderHandle is a concrete subclass of ResourceHandle that represents the
- * persisted state of a GlslShader, and is used by any
- * {@link AbstractGlslShaderResourceDriver} when they manage GlslShaders.
+ * GlslShaderHandle is the handle type that represents the persisted state of a
+ * GlslShader, and is used by any {@link AbstractGlslShaderResourceDriver}.
  * 
  * @author Michael Ludwig
  */
-public class GlslShaderHandle extends ResourceHandle {
+public class GlslShaderHandle {
     public static class Uniform {
         public final String name;
         public final int index;
     public final EnumMap<ShaderType, Integer> shaders;
     public final EnumMap<ShaderType, String> shaderSource;
     
-    public final int programID;
+    public int programID;
     
-    public GlslShaderHandle(GlslShader shader, int programID) {
-        super(shader);
-        
-        this.programID = programID;
-        
+    public GlslShaderHandle() {
         attributes = new HashMap<String, Attribute>();
         uniforms = new HashMap<String, Uniform>();
         shaders = new EnumMap<ShaderType, Integer>(ShaderType.class);
         shaderSource = new EnumMap<ShaderType, String>(ShaderType.class);
+        
+        programID = 0;
     }
 }

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/drivers/TextureHandle.java

 package com.ferox.renderer.impl.drivers;
 
 import com.ferox.renderer.Renderer.Comparison;
-import com.ferox.renderer.impl.ResourceHandle;
 import com.ferox.resource.BufferData.DataType;
 import com.ferox.resource.Texture;
 import com.ferox.resource.Texture.Filter;
 import com.ferox.resource.TextureFormat;
 
 /**
- * TextureHandle is a concrete subclass of ResourceHandle that represents the
- * persisted state of a Texture, and is used by any
- * {@link AbstractTextureResourceDriver} when they manage Textures.
+ * TextureHandle is the handle that represents the persisted state of a Texture,
+ * and is used by any {@link AbstractTextureResourceDriver}.
  * 
  * @author Michael Ludwig
  */
-public class TextureHandle extends ResourceHandle {
+public class TextureHandle {
     public final Target target;
     public final int texID;
     
     public float anisoLevel;
     
     public TextureHandle(Texture texture) {
-        super(texture);
         texID = texture.getId();
         target = texture.getTarget();
         lastSyncedKeys = new Object[texture.getNumLayers()][];

File ferox-renderer/ferox-renderer-impl/src/main/java/com/ferox/renderer/impl/drivers/VertexBufferObjectHandle.java

 
 import java.nio.Buffer;
 
-import com.ferox.renderer.impl.ResourceHandle;
 import com.ferox.resource.BufferData.DataType;
 import com.ferox.resource.VertexBufferObject;
 import com.ferox.resource.VertexBufferObject.StorageMode;
 
 /**
- * VertexBufferObjectHandle is a concrete subclass of ResourceHandle that
- * represents the persisted state of a VertexBufferObject, and is used by any
- * {@link AbstractVertexBufferObjectResourceDriver} when they manage
- * VertexBufferObjects.
+ * VertexBufferObjectHandle is the handle type that represents the persisted
+ * state of a VertexBufferObject, and is used by all
+ * {@link AbstractVertexBufferObjectResourceDriver}.
  * 
  * @author Michael Ludwig
  */
-public class VertexBufferObjectHandle extends ResourceHandle {
+public class VertexBufferObjectHandle {
     public DataType dataType;
     public int length;
     
     public final int vboID;
     
     public VertexBufferObjectHandle(VertexBufferObject res) {
-        super(res);
-        
         vboID = res.getId();
         
         // blank parameters