diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java index c931531bc2..4822ec3a05 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java @@ -31,6 +31,8 @@ */ package com.jme3.renderer; +import java.lang.ref.WeakReference; + import com.jme3.material.RenderState; import com.jme3.math.ColorRGBA; import com.jme3.scene.Mesh; @@ -219,7 +221,7 @@ public class RenderContext { * * @see Renderer#setTexture(int, com.jme3.texture.Texture) */ - public final Image[] boundTextures = new Image[16]; + public final WeakReference boundTextures[] = new WeakReference[16]; /** * IDList for texture units @@ -252,7 +254,7 @@ public class RenderContext { * Vertex attribs currently bound and enabled. If a slot is null, then * it is disabled. */ - public final VertexBuffer[] boundAttribs = new VertexBuffer[16]; + public final WeakReference [] boundAttribs = new WeakReference[16]; /** * IDList for vertex attributes diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index daccf3c5cc..8c55881e4d 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -62,6 +62,7 @@ import com.jme3.util.NativeObjectManager; import jme3tools.shader.ShaderDebug; +import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; @@ -2385,9 +2386,9 @@ private void bindTextureAndUnit(int target, Image img, int unit) { gl.glActiveTexture(GL.GL_TEXTURE0 + unit); context.boundTextureUnit = unit; } - if (context.boundTextures[unit] != img) { + if (context.boundTextures[unit]==null||context.boundTextures[unit].get() != img.getWeakRef().get()) { gl.glBindTexture(target, img.getId()); - context.boundTextures[unit] = img; + context.boundTextures[unit] = img.getWeakRef(); statistics.onTextureUse(img, true); } else { statistics.onTextureUse(img, false); @@ -2403,13 +2404,13 @@ private void bindTextureAndUnit(int target, Image img, int unit) { * @param unit At what unit to bind the texture. */ private void bindTextureOnly(int target, Image img, int unit) { - if (context.boundTextures[unit] != img) { + if (context.boundTextures[unit] == null || context.boundTextures[unit].get() != img.getWeakRef().get()) { if (context.boundTextureUnit != unit) { gl.glActiveTexture(GL.GL_TEXTURE0 + unit); context.boundTextureUnit = unit; } gl.glBindTexture(target, img.getId()); - context.boundTextures[unit] = img; + context.boundTextures[unit] = img.getWeakRef(); statistics.onTextureUse(img, true); } else { statistics.onTextureUse(img, false); @@ -2824,7 +2825,7 @@ public void clearVertexAttribs() { for (int i = 0; i < attribList.oldLen; i++) { int idx = attribList.oldList[i]; gl.glDisableVertexAttribArray(idx); - if (context.boundAttribs[idx].isInstanced()) { + if (context.boundAttribs[idx].get().isInstanced()) { glext.glVertexAttribDivisorARB(idx, 0); } context.boundAttribs[idx] = null; @@ -2879,13 +2880,13 @@ public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) { updateBufferData(vb); } - VertexBuffer[] attribs = context.boundAttribs; + WeakReference[] attribs = context.boundAttribs; for (int i = 0; i < slotsRequired; i++) { if (!context.attribIndexList.moveToNew(loc + i)) { gl.glEnableVertexAttribArray(loc + i); } } - if (attribs[loc] != vb) { + if (attribs[loc]==null||attribs[loc].get() != vb) { // NOTE: Use id from interleaved buffer if specified int bufId = idb != null ? idb.getId() : vb.getId(); assert bufId != -1; @@ -2925,14 +2926,14 @@ public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) { for (int i = 0; i < slotsRequired; i++) { int slot = loc + i; - if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) { + if (vb.isInstanced() && (attribs[slot] == null || attribs[slot].get() == null || !attribs[slot].get().isInstanced())) { // non-instanced -> instanced glext.glVertexAttribDivisorARB(slot, vb.getInstanceSpan()); - } else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) { + } else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].get() != null && attribs[slot].get().isInstanced()) { // instanced -> non-instanced glext.glVertexAttribDivisorARB(slot, 0); } - attribs[slot] = vb; + attribs[slot] = vb.getWeakRef(); } } } diff --git a/jme3-core/src/main/java/com/jme3/util/NativeObject.java b/jme3-core/src/main/java/com/jme3/util/NativeObject.java index 727250b70a..8099ea6068 100644 --- a/jme3-core/src/main/java/com/jme3/util/NativeObject.java +++ b/jme3-core/src/main/java/com/jme3/util/NativeObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2019 jMonkeyEngine + * Copyright (c) 2009-2020 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,6 +31,7 @@ */ package com.jme3.util; +import java.lang.ref.WeakReference; import java.nio.Buffer; /** @@ -79,6 +80,8 @@ public abstract class NativeObject implements Cloneable { */ protected boolean updateNeeded = true; + private WeakReference weakRef; + /** * Creates a new GLObject. Should be * called by the subclasses. @@ -227,4 +230,17 @@ public void dispose() { objectManager.enqueueUnusedObject(this); } } + + /** + * Acquire a weak reference to this NativeObject. + * + * @param the type + * @return a weak reference (possibly a pre-existing one) + */ + public WeakReference getWeakRef() { + if (weakRef == null) { + weakRef = new WeakReference<>(this); + } + return (WeakReference) weakRef; + } }