diff --git a/engine/src/core/com/jme3/audio/AudioBuffer.java b/engine/src/core/com/jme3/audio/AudioBuffer.java index 82515adbf..5811fe4f5 100644 --- a/engine/src/core/com/jme3/audio/AudioBuffer.java +++ b/engine/src/core/com/jme3/audio/AudioBuffer.java @@ -32,6 +32,7 @@ package com.jme3.audio; import com.jme3.audio.AudioData.DataType; +import com.jme3.util.BufferUtils; import com.jme3.util.NativeObject; import java.nio.ByteBuffer; @@ -102,10 +103,13 @@ public class AudioBuffer extends AudioData { setUpdateNeeded(); } - public void deleteObject(AudioRenderer ar) { - + @Override + protected void deleteNativeBuffers() { + if (audioData != null) { + BufferUtils.destroyDirectBuffer(audioData); + } } - + @Override public void deleteObject(Object rendererObject) { ((AudioRenderer)rendererObject).deleteAudioData(this); diff --git a/engine/src/core/com/jme3/audio/AudioData.java b/engine/src/core/com/jme3/audio/AudioData.java index 9bfb14143..750aa1f84 100644 --- a/engine/src/core/com/jme3/audio/AudioData.java +++ b/engine/src/core/com/jme3/audio/AudioData.java @@ -53,11 +53,11 @@ public abstract class AudioData extends NativeObject { } public AudioData(){ - super(AudioData.class); + super(); } protected AudioData(int id){ - super(AudioData.class, id); + super(id); } /** diff --git a/engine/src/core/com/jme3/audio/Filter.java b/engine/src/core/com/jme3/audio/Filter.java index e4d9101be..b46270c11 100644 --- a/engine/src/core/com/jme3/audio/Filter.java +++ b/engine/src/core/com/jme3/audio/Filter.java @@ -40,11 +40,11 @@ import java.io.IOException; public abstract class Filter extends NativeObject implements Savable { public Filter(){ - super(Filter.class); + super(); } protected Filter(int id){ - super(Filter.class, id); + super(id); } public void write(JmeExporter ex) throws IOException { diff --git a/engine/src/core/com/jme3/renderer/Caps.java b/engine/src/core/com/jme3/renderer/Caps.java index bc0ab0929..55a94c6ee 100644 --- a/engine/src/core/com/jme3/renderer/Caps.java +++ b/engine/src/core/com/jme3/renderer/Caps.java @@ -32,6 +32,7 @@ package com.jme3.renderer; import com.jme3.shader.Shader; +import com.jme3.shader.Shader.ShaderSource; import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer.RenderBuffer; import com.jme3.texture.Image; @@ -346,29 +347,30 @@ public enum Caps { * @return True if it is supported, false otherwise. */ public static boolean supports(Collection caps, Shader shader){ - String lang = shader.getLanguage(); - if (lang.startsWith("GLSL")){ - int ver = Integer.parseInt(lang.substring(4)); - switch (ver){ - case 100: - return caps.contains(Caps.GLSL100); - case 110: - return caps.contains(Caps.GLSL110); - case 120: - return caps.contains(Caps.GLSL120); - case 130: - return caps.contains(Caps.GLSL130); - case 140: - return caps.contains(Caps.GLSL140); - case 150: - return caps.contains(Caps.GLSL150); - case 330: - return caps.contains(Caps.GLSL330); - default: - return false; + for (ShaderSource source : shader.getSources()) { + if (source.getLanguage().startsWith("GLSL")) { + int ver = Integer.parseInt(source.getLanguage().substring(4)); + switch (ver) { + case 100: + if (!caps.contains(Caps.GLSL100)) return false; + case 110: + if (!caps.contains(Caps.GLSL110)) return false; + case 120: + if (!caps.contains(Caps.GLSL120)) return false; + case 130: + if (!caps.contains(Caps.GLSL130)) return false; + case 140: + if (!caps.contains(Caps.GLSL140)) return false; + case 150: + if (!caps.contains(Caps.GLSL150)) return false; + case 330: + if (!caps.contains(Caps.GLSL330)) return false; + default: + return false; + } } } - return false; + return true; } } diff --git a/engine/src/core/com/jme3/scene/VertexBuffer.java b/engine/src/core/com/jme3/scene/VertexBuffer.java index ea5e26bb0..4b7896b61 100644 --- a/engine/src/core/com/jme3/scene/VertexBuffer.java +++ b/engine/src/core/com/jme3/scene/VertexBuffer.java @@ -319,7 +319,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { * Must call setupData() to initialize. */ public VertexBuffer(Type type){ - super(VertexBuffer.class); + super(); this.bufType = type; } @@ -327,13 +327,54 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { * Serialization only. Do not use. */ public VertexBuffer(){ - super(VertexBuffer.class); + super(); } protected VertexBuffer(int id){ - super(VertexBuffer.class, id); + super(id); } + public boolean invariant() { + // Does the VB hold any data? + if (data == null) { + throw new AssertionError(); + } + // Does offset exceed buffer limit or negative? + if (offset > data.limit() || offset < 0) { + throw new AssertionError(); + } + // Are components between 1 and 4? + if (components < 1 || components > 4) { + throw new AssertionError(); + } + + // Does usage comply with buffer directness? + //if (usage == Usage.CpuOnly && data.isDirect()) { + // throw new AssertionError(); + /*} else*/ if (usage != Usage.CpuOnly && !data.isDirect()) { + throw new AssertionError(); + } + + // Double/Char/Long buffers are not supported for VertexBuffers. + // For the rest, ensure they comply with the "Format" value. + if (data instanceof DoubleBuffer) { + throw new AssertionError(); + } else if (data instanceof CharBuffer) { + throw new AssertionError(); + } else if (data instanceof LongBuffer) { + throw new AssertionError(); + } else if (data instanceof FloatBuffer && format != Format.Float) { + throw new AssertionError(); + } else if (data instanceof IntBuffer && format != Format.Int && format != Format.UnsignedInt) { + throw new AssertionError(); + } else if (data instanceof ShortBuffer && format != Format.Short && format != Format.UnsignedShort) { + throw new AssertionError(); + } else if (data instanceof ByteBuffer && format != Format.Byte && format != Format.UnsignedByte) { + throw new AssertionError(); + } + return true; + } + /** * @return The offset after which the data is sent to the GPU. * @@ -950,7 +991,14 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { public void deleteObject(Object rendererObject) { ((Renderer)rendererObject).deleteBuffer(this); } - + + @Override + protected void deleteNativeBuffers() { + if (data != null) { + BufferUtils.destroyDirectBuffer(data); + } + } + @Override public NativeObject createDestructableClone(){ return new VertexBuffer(id); diff --git a/engine/src/core/com/jme3/shader/Shader.java b/engine/src/core/com/jme3/shader/Shader.java index cee91e8fd..308b5dfd8 100644 --- a/engine/src/core/com/jme3/shader/Shader.java +++ b/engine/src/core/com/jme3/shader/Shader.java @@ -41,14 +41,6 @@ import java.util.ArrayList; import java.util.Collection; public final class Shader extends NativeObject { - - /** - * - * @deprecated shader language now specified per shader source. See - * {@link ShaderSource#setLanguage(String) - */ - @Deprecated - private String language; /** * A list of all shader sources currently attached. @@ -98,7 +90,7 @@ public final class Shader extends NativeObject { String defines; public ShaderSource(ShaderType type){ - super(ShaderSource.class); + super(); this.sourceType = type; if (type == null) { throw new IllegalArgumentException("The shader type must be specified"); @@ -106,13 +98,13 @@ public final class Shader extends NativeObject { } protected ShaderSource(ShaderSource ss){ - super(ShaderSource.class, ss.id); + super(ss.id); // No data needs to be copied. // (This is a destructable clone) } public ShaderSource(){ - super(ShaderSource.class); + super(); } public void setName(String name){ @@ -190,17 +182,6 @@ public final class Shader extends NativeObject { } } - /** - * @deprecated Shader sources are now associated with the shader - * language. - */ - @Deprecated - public Shader(String language){ - super(Shader.class); - this.language = language; - initialize(); - } - /** * Initializes the shader for use, must be called after the * constructor without arguments is used. @@ -216,14 +197,14 @@ public final class Shader extends NativeObject { * after this constructor for the shader to be usable. */ public Shader(){ - super(Shader.class); + super(); } /** * Do not use this constructor. Used for destructable clones only. */ protected Shader(Shader s){ - super(Shader.class, s.id); + super(s.id); // Shader sources cannot be shared, therefore they must // be destroyed together with the parent shader. @@ -233,43 +214,6 @@ public final class Shader extends NativeObject { } } - /** - * @deprecated Use the method that takes a language argument instead. - * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) } - */ - @Deprecated - public void addSource(ShaderType type, String name, String source, String defines) { - addSource(type, name, source, defines, this.language); - } - - /** - * @deprecated Use the method that takes a language argument instead. - * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) } - */ - @Deprecated - public void addSource(ShaderType type, String source, String defines){ - addSource(type, null, source, defines); - } - - /** - * @deprecated Use the method that takes a language argument instead. - * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) } - */ - @Deprecated - public void addSource(ShaderType type, String source){ - addSource(type, source, null); - } - - /** - * @deprecated Shader sources may not be shared. - * {@link #addSource(com.jme3.shader.Shader.ShaderType, java.lang.String, java.lang.String, java.lang.String, java.lang.String) } - */ - @Deprecated - private void addSource(ShaderSource source){ - shaderSourceList.add(source); - setUpdateNeeded(); - } - /** * Adds source code to a certain pipeline. * @@ -324,15 +268,6 @@ public final class Shader extends NativeObject { return shaderSourceList; } - /** - * @deprecated Shaders no longer have a language variable, - * use {@link ShaderSource#getLanguage() } instead. - */ - @Deprecated - public String getLanguage(){ - return language; - } - @Override public String toString() { return getClass().getSimpleName() + @@ -341,33 +276,6 @@ public final class Shader extends NativeObject { ", shaderSources=" + getSources() + "]"; } - /** - * @deprecated This method is not needed since deleting - * a shader causes the sources to delete as well, thus its not required - * for them to be GC'd to be removed from GL. - */ - @Deprecated - public void resetSources(){ - shaderSourceList.clear(); - } - - /** - * @deprecated Unusable shaders cause the renderer to crash, - * therefore this field no longer serves any purpose. - */ - @Deprecated - public boolean isUsable(){ - return true; - } - - /** - * @deprecated Unusable shaders cause the renderer to crash, - * therefore this field no longer serves any purpose. - */ - @Deprecated - public void setUsable(boolean usable){ - } - /** * Usually called when the shader itself changes or during any * time when the variable locations need to be refreshed. diff --git a/engine/src/core/com/jme3/texture/FrameBuffer.java b/engine/src/core/com/jme3/texture/FrameBuffer.java index d00338c6c..ae067903d 100644 --- a/engine/src/core/com/jme3/texture/FrameBuffer.java +++ b/engine/src/core/com/jme3/texture/FrameBuffer.java @@ -175,7 +175,7 @@ public class FrameBuffer extends NativeObject { * @throws IllegalArgumentException If width or height are not positive. */ public FrameBuffer(int width, int height, int samples){ - super(FrameBuffer.class); + super(); if (width <= 0 || height <= 0) throw new IllegalArgumentException("FrameBuffer must have valid size."); @@ -185,7 +185,7 @@ public class FrameBuffer extends NativeObject { } protected FrameBuffer(FrameBuffer src){ - super(FrameBuffer.class, src.id); + super(src.id); /* for (RenderBuffer renderBuf : src.colorBufs){ RenderBuffer clone = renderBuf.createDestructableClone(); diff --git a/engine/src/core/com/jme3/texture/Image.java b/engine/src/core/com/jme3/texture/Image.java index 02ffc0f6b..a3dc2d2a5 100644 --- a/engine/src/core/com/jme3/texture/Image.java +++ b/engine/src/core/com/jme3/texture/Image.java @@ -34,6 +34,7 @@ package com.jme3.texture; import com.jme3.export.*; import com.jme3.renderer.Caps; import com.jme3.renderer.Renderer; +import com.jme3.util.BufferUtils; import com.jme3.util.NativeObject; import java.io.IOException; import java.nio.ByteBuffer; @@ -375,6 +376,13 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ { setUpdateNeeded(); } + @Override + protected void deleteNativeBuffers() { + for (ByteBuffer buf : data) { + BufferUtils.destroyDirectBuffer(buf); + } + } + @Override public void deleteObject(Object rendererObject) { ((Renderer)rendererObject).deleteImage(this); @@ -402,12 +410,12 @@ public class Image extends NativeObject implements Savable /*, Cloneable*/ { * are undefined. */ public Image() { - super(Image.class); + super(); data = new ArrayList(1); } protected Image(int id){ - super(Image.class, id); + super(id); } /** diff --git a/engine/src/core/com/jme3/util/NativeObject.java b/engine/src/core/com/jme3/util/NativeObject.java index 93b076255..e9f637ee7 100644 --- a/engine/src/core/com/jme3/util/NativeObject.java +++ b/engine/src/core/com/jme3/util/NativeObject.java @@ -31,6 +31,8 @@ */ package com.jme3.util; +import java.nio.Buffer; + /** * Describes a native object. An encapsulation of a certain object * on the native side of the graphics or audio library. @@ -41,11 +43,13 @@ package com.jme3.util; */ public abstract class NativeObject implements Cloneable { + public static final int INVALID_ID = -1; + /** * The ID of the object, usually depends on its type. * Typically returned from calls like glGenTextures, glGenBuffers, etc. */ - protected int id = -1; + protected int id = INVALID_ID; /** * A reference to a "handle". By hard referencing a certain object, it's @@ -60,19 +64,13 @@ public abstract class NativeObject implements Cloneable { */ protected boolean updateNeeded = true; - /** - * The type of the GLObject, usually specified by a subclass. - */ - protected final Class type; - /** * Creates a new GLObject with the given type. Should be * called by the subclasses. * * @param type The type that the subclass represents. */ - public NativeObject(Class type){ - this.type = type; + public NativeObject(){ this.handleRef = new Object(); } @@ -80,8 +78,7 @@ public abstract class NativeObject implements Cloneable { * Protected constructor that doesn't allocate handle ref. * This is used in subclasses for the createDestructableClone(). */ - protected NativeObject(Class type, int id){ - this.type = type; + protected NativeObject(int id){ this.id = id; } @@ -91,9 +88,9 @@ public abstract class NativeObject implements Cloneable { * @param id The ID to set */ public void setId(int id){ - if (this.id != -1) + if (this.id != INVALID_ID) { throw new IllegalStateException("ID has already been set for this GL object."); - + } this.id = id; } @@ -129,7 +126,7 @@ public abstract class NativeObject implements Cloneable { @Override public String toString(){ - return "Native" + type.getSimpleName() + " " + id; + return "Native" + getClass().getSimpleName() + " " + id; } /** @@ -137,18 +134,40 @@ public abstract class NativeObject implements Cloneable { * createDestructableClone(). */ @Override - protected NativeObject clone(){ - try{ + protected NativeObject clone() { + try { NativeObject obj = (NativeObject) super.clone(); obj.handleRef = new Object(); - obj.id = -1; + obj.id = INVALID_ID; obj.updateNeeded = true; return obj; - }catch (CloneNotSupportedException ex){ + } catch (CloneNotSupportedException ex) { throw new AssertionError(); } } + /** + * Deletes any associated native {@link Buffer buffers}. + * This is necessary because it is unlikely that native buffers + * will be garbage collected naturally (due to how GC works), therefore + * the collection must be handled manually. + * + * Only implementations that manage native buffers need to override + * this method. Note that the behavior that occurs when a + * deleted native buffer is used is not defined, therefore this + * method is protected + */ + protected void deleteNativeBuffers() { + } + + /** + * Package-private version of {@link #deleteNativeBuffers() }, to be used + * from the {@link NativeObjectManager}. + */ + void deleteNativeBuffersInternal() { + deleteNativeBuffers(); + } + /** * Called when the GL context is restarted to reset all IDs. Prevents * "white textures" on display restart. @@ -162,7 +181,7 @@ public abstract class NativeObject implements Cloneable { * @param rendererObject The renderer to be used to delete the object */ public abstract void deleteObject(Object rendererObject); - + /** * Creates a shallow clone of this GL Object. The deleteObject method * should be functional for this object. diff --git a/engine/src/tools/jme3tools/shadercheck/CgcValidator.java b/engine/src/tools/jme3tools/shadercheck/CgcValidator.java index 28dbf21f3..c5f314711 100644 --- a/engine/src/tools/jme3tools/shadercheck/CgcValidator.java +++ b/engine/src/tools/jme3tools/shadercheck/CgcValidator.java @@ -95,15 +95,14 @@ public class CgcValidator implements Validator { } public void validate(Shader shader, StringBuilder results) { - String language = shader.getLanguage(); for (ShaderSource source : shader.getSources()){ results.append("Checking: ").append(source.getName()); switch (source.getType()){ case Fragment: - executeCg(source.getSource(), language, source.getDefines(), "arbfp1", results); + executeCg(source.getSource(), source.getLanguage(), source.getDefines(), "arbfp1", results); break; case Vertex: - executeCg(source.getSource(), language, source.getDefines(), "arbvp1", results); + executeCg(source.getSource(), source.getLanguage(), source.getDefines(), "arbvp1", results); break; } } diff --git a/engine/src/tools/jme3tools/shadercheck/GpuAnalyzerValidator.java b/engine/src/tools/jme3tools/shadercheck/GpuAnalyzerValidator.java index c2b8973e1..d06f26c88 100644 --- a/engine/src/tools/jme3tools/shadercheck/GpuAnalyzerValidator.java +++ b/engine/src/tools/jme3tools/shadercheck/GpuAnalyzerValidator.java @@ -105,15 +105,14 @@ public class GpuAnalyzerValidator implements Validator { } public void validate(Shader shader, StringBuilder results) { - String language = shader.getLanguage(); for (ShaderSource source : shader.getSources()){ results.append("Checking: ").append(source.getName()); switch (source.getType()){ case Fragment: - executeAnalyzer(source.getSource(), language, source.getDefines(), "HD5770", results); + executeAnalyzer(source.getSource(), source.getLanguage(), source.getDefines(), "HD5770", results); break; case Vertex: - executeAnalyzer(source.getSource(), language, source.getDefines(), "HD5770", results); + executeAnalyzer(source.getSource(), source.getLanguage(), source.getDefines(), "HD5770", results); break; } }