Skip to content

Commit 394fa89

Browse files
committed
refactored GL-resource disposal mechanism
1 parent a5802e6 commit 394fa89

File tree

1 file changed

+69
-137
lines changed

1 file changed

+69
-137
lines changed

core/src/processing/opengl/PGraphicsOpenGL.java

Lines changed: 69 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import processing.android.AppComponent;
2828
import processing.core.*;
29-
3029
import java.lang.ref.ReferenceQueue;
3130
import java.lang.ref.WeakReference;
3231
import java.net.URL;
@@ -49,6 +48,43 @@ public class PGraphicsOpenGL extends PGraphics {
4948

5049
// ........................................................
5150

51+
// Disposal of native resources
52+
// Using the technique alternative to finalization described in:
53+
// http://www.oracle.com/technetwork/articles/java/finalization-137655.html
54+
private static ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
55+
private static List<Disposable<? extends Object>> reachableWeakReferences =
56+
new LinkedList<>();
57+
58+
static final private int MAX_DRAIN_GLRES_ITERATIONS = 10;
59+
60+
static void drainRefQueueBounded() {
61+
int iterations = 0;
62+
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
63+
Disposable<? extends Object> res =
64+
(Disposable<? extends Object>) refQueue.poll();
65+
if (res == null) {
66+
break;
67+
}
68+
res.dispose();
69+
++iterations;
70+
}
71+
}
72+
73+
private static abstract class Disposable<T> extends WeakReference<T> {
74+
protected Disposable(T obj) {
75+
super(obj, refQueue);
76+
drainRefQueueBounded();
77+
reachableWeakReferences.add(this);
78+
}
79+
80+
public void dispose() {
81+
reachableWeakReferences.remove(this);
82+
disposeNative();
83+
}
84+
85+
abstract public void disposeNative();
86+
}
87+
5288
// Basic rendering parameters:
5389

5490
/** Whether the PGraphics object is ready to render or not. */
@@ -829,55 +865,28 @@ protected void removeFontTexture(PFont font) {
829865

830866
//////////////////////////////////////////////////////////////
831867

832-
// RESOURCE HANDLING
833-
// Using the technique alternative to finalization described in:
834-
// http://www.oracle.com/technetwork/articles/java/finalization-137655.html
835-
836-
static final private int MAX_DRAIN_GLRES_ITERATIONS = 10;
837868

838-
protected static class GLResourceTexture extends WeakReference<Texture> {
869+
protected static class GLResourceTexture extends Disposable<Texture> {
839870
int glName;
840871

841872
private PGL pgl;
842873
private int context;
843874

844-
static private ReferenceQueue<Texture> refQueue = new ReferenceQueue<Texture>();
845-
static private List<GLResourceTexture> refList = new ArrayList<GLResourceTexture>();
846-
847-
static void drainRefQueueBounded() {
848-
ReferenceQueue<Texture> refQueue = GLResourceTexture.referenceQueue();
849-
int iterations = 0;
850-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
851-
GLResourceTexture res = (GLResourceTexture)refQueue.poll();
852-
if (res == null) {
853-
break;
854-
}
855-
res.dispose();
856-
++iterations;
857-
}
858-
}
859-
860-
static ReferenceQueue<Texture> referenceQueue() {
861-
return refQueue;
862-
}
863-
864875
public GLResourceTexture(Texture tex) {
865-
super(tex, refQueue);
876+
super(tex);
866877

867-
drainRefQueueBounded();
868878

869879
pgl = tex.pg.getPrimaryPGL();
870880
pgl.genTextures(1, intBuffer);
871881
tex.glName = intBuffer.get(0);
872882

873883
this.glName = tex.glName;
874884
this.context = tex.context;
875-
876-
refList.add(this);
877885
}
878886

879-
private void disposeNative() {
880-
if (pgl != null && pgl.contextIsCurrent(context)) {
887+
@Override
888+
public void disposeNative() {
889+
if (pgl != null) {
881890
if (glName != 0) {
882891
intBuffer.put(0, glName);
883892
pgl.deleteTextures(1, intBuffer);
@@ -887,13 +896,11 @@ private void disposeNative() {
887896
}
888897
}
889898

890-
void dispose() {
891-
refList.remove(this);
892-
disposeNative();
893-
}
894-
895899
@Override
896900
public boolean equals(Object obj) {
901+
if (!(obj instanceof GLResourceTexture)) {
902+
return false;
903+
}
897904
GLResourceTexture other = (GLResourceTexture)obj;
898905
return other.glName == glName &&
899906
other.context == context;
@@ -909,49 +916,26 @@ public int hashCode() {
909916
}
910917

911918

912-
protected static class GLResourceVertexBuffer extends WeakReference<VertexBuffer> {
919+
protected static class GLResourceVertexBuffer extends Disposable<VertexBuffer> {
913920
int glId;
914921

915922
private PGL pgl;
916923
private int context;
917924

918-
static private ReferenceQueue<VertexBuffer> refQueue = new ReferenceQueue<VertexBuffer>();
919-
static private List<GLResourceVertexBuffer> refList = new ArrayList<GLResourceVertexBuffer>();
920-
921-
static void drainRefQueueBounded() {
922-
ReferenceQueue<VertexBuffer> refQueue = GLResourceVertexBuffer.referenceQueue();
923-
int iterations = 0;
924-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
925-
GLResourceVertexBuffer res = (GLResourceVertexBuffer)refQueue.poll();
926-
if (res == null) {
927-
break;
928-
}
929-
res.dispose();
930-
++iterations;
931-
}
932-
}
933-
934-
static ReferenceQueue<VertexBuffer> referenceQueue() {
935-
return refQueue;
936-
}
937-
938925
public GLResourceVertexBuffer(VertexBuffer vbo) {
939-
super(vbo, refQueue);
940-
941-
drainRefQueueBounded();
926+
super(vbo);
942927

943928
pgl = vbo.pgl.graphics.getPrimaryPGL();
944929
pgl.genBuffers(1, intBuffer);
945930
vbo.glId = intBuffer.get(0);
946931

947932
this.glId = vbo.glId;
948933
this.context = vbo.context;
949-
950-
refList.add(this);
951934
}
952935

953-
private void disposeNative() {
954-
if (pgl != null && pgl.contextIsCurrent(context)) {
936+
@Override
937+
public void disposeNative() {
938+
if (pgl != null) {
955939
if (glId != 0) {
956940
intBuffer.put(0, glId);
957941
pgl.deleteBuffers(1, intBuffer);
@@ -961,13 +945,11 @@ private void disposeNative() {
961945
}
962946
}
963947

964-
void dispose() {
965-
refList.remove(this);
966-
disposeNative();
967-
}
968-
969948
@Override
970949
public boolean equals(Object obj) {
950+
if (!(obj instanceof GLResourceVertexBuffer)) {
951+
return false;
952+
}
971953
GLResourceVertexBuffer other = (GLResourceVertexBuffer)obj;
972954
return other.glId == glId &&
973955
other.context == context;
@@ -983,38 +965,16 @@ public int hashCode() {
983965
}
984966

985967

986-
protected static class GLResourceShader extends WeakReference<PShader> {
968+
protected static class GLResourceShader extends Disposable<PShader> {
987969
int glProgram;
988970
int glVertex;
989971
int glFragment;
990972

991973
private PGL pgl;
992974
private int context;
993975

994-
static private ReferenceQueue<PShader> refQueue = new ReferenceQueue<PShader>();
995-
static private List<GLResourceShader> refList = new ArrayList<GLResourceShader>();
996-
997-
static void drainRefQueueBounded() {
998-
ReferenceQueue<PShader> refQueue = GLResourceShader.referenceQueue();
999-
int iterations = 0;
1000-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
1001-
GLResourceShader res = (GLResourceShader)refQueue.poll();
1002-
if (res == null) {
1003-
break;
1004-
}
1005-
res.dispose();
1006-
++iterations;
1007-
}
1008-
}
1009-
1010-
static ReferenceQueue<PShader> referenceQueue() {
1011-
return refQueue;
1012-
}
1013-
1014976
public GLResourceShader(PShader sh) {
1015-
super(sh, refQueue);
1016-
1017-
drainRefQueueBounded();
977+
super(sh);
1018978

1019979
this.pgl = sh.pgl.graphics.getPrimaryPGL();
1020980
sh.glProgram = pgl.createProgram();
@@ -1026,12 +986,11 @@ public GLResourceShader(PShader sh) {
1026986
this.glFragment = sh.glFragment;
1027987

1028988
this.context = sh.context;
1029-
1030-
refList.add(this);
1031989
}
1032990

1033-
private void disposeNative() {
1034-
if (pgl != null && pgl.contextIsCurrent(context)) {
991+
@Override
992+
public void disposeNative() {
993+
if (pgl != null) {
1035994
if (glFragment != 0) {
1036995
pgl.deleteShader(glFragment);
1037996
glFragment = 0;
@@ -1048,13 +1007,11 @@ private void disposeNative() {
10481007
}
10491008
}
10501009

1051-
void dispose() {
1052-
refList.remove(this);
1053-
disposeNative();
1054-
}
1055-
10561010
@Override
10571011
public boolean equals(Object obj) {
1012+
if (!(obj instanceof GLResourceShader)) {
1013+
return false;
1014+
}
10581015
GLResourceShader other = (GLResourceShader)obj;
10591016
return other.glProgram == glProgram &&
10601017
other.glVertex == glVertex &&
@@ -1074,7 +1031,7 @@ public int hashCode() {
10741031
}
10751032

10761033

1077-
protected static class GLResourceFrameBuffer extends WeakReference<FrameBuffer> {
1034+
protected static class GLResourceFrameBuffer extends Disposable<FrameBuffer> {
10781035
int glFbo;
10791036
int glDepth;
10801037
int glStencil;
@@ -1084,30 +1041,8 @@ protected static class GLResourceFrameBuffer extends WeakReference<FrameBuffer>
10841041
private PGL pgl;
10851042
private int context;
10861043

1087-
static private ReferenceQueue<FrameBuffer> refQueue = new ReferenceQueue<FrameBuffer>();
1088-
static private List<GLResourceFrameBuffer> refList = new ArrayList<GLResourceFrameBuffer>();
1089-
1090-
static void drainRefQueueBounded() {
1091-
ReferenceQueue<FrameBuffer> refQueue = GLResourceFrameBuffer.referenceQueue();
1092-
int iterations = 0;
1093-
while (iterations < MAX_DRAIN_GLRES_ITERATIONS) {
1094-
GLResourceFrameBuffer res = (GLResourceFrameBuffer)refQueue.poll();
1095-
if (res == null) {
1096-
break;
1097-
}
1098-
res.dispose();
1099-
++iterations;
1100-
}
1101-
}
1102-
1103-
static ReferenceQueue<FrameBuffer> referenceQueue() {
1104-
return refQueue;
1105-
}
1106-
11071044
public GLResourceFrameBuffer(FrameBuffer fb) {
1108-
super(fb, refQueue);
1109-
1110-
drainRefQueueBounded();
1045+
super(fb);
11111046

11121047
pgl = fb.pg.getPrimaryPGL();
11131048
if (!fb.screenFb) {
@@ -1141,12 +1076,11 @@ public GLResourceFrameBuffer(FrameBuffer fb) {
11411076
}
11421077

11431078
this.context = fb.context;
1144-
1145-
refList.add(this);
11461079
}
11471080

1148-
private void disposeNative() {
1149-
if (pgl != null && pgl.contextIsCurrent(context)) {
1081+
@Override
1082+
public void disposeNative() {
1083+
if (pgl != null) {
11501084
if (glFbo != 0) {
11511085
intBuffer.put(0, glFbo);
11521086
pgl.deleteFramebuffers(1, intBuffer);
@@ -1176,13 +1110,11 @@ private void disposeNative() {
11761110
}
11771111
}
11781112

1179-
void dispose() {
1180-
refList.remove(this);
1181-
disposeNative();
1182-
}
1183-
11841113
@Override
11851114
public boolean equals(Object obj) {
1115+
if (!(obj instanceof GLResourceFrameBuffer)) {
1116+
return false;
1117+
}
11861118
GLResourceFrameBuffer other = (GLResourceFrameBuffer)obj;
11871119
return other.glFbo == glFbo &&
11881120
other.glDepth == glDepth &&

0 commit comments

Comments
 (0)