Project

General

Profile

« Previous | Next » 

Revision 9ec374e8

Added by Leszek Koltunski over 3 years ago

More support for using the library from more than one activity

View differences:

src/main/java/org/distorted/library/effectqueue/EffectQueue.java
24 24
import org.distorted.library.effect.EffectType;
25 25
import org.distorted.library.main.DistortedLibrary;
26 26
import org.distorted.library.main.InternalMaster;
27
import org.distorted.library.main.InternalStackFrameList;
27 28

  
28 29
import java.util.ArrayList;
29 30
import java.util.HashMap;
......
239 240

  
240 241
  public static boolean setMax(int index, int m)
241 242
    {
242
    if( !DistortedLibrary.isInitialized() || m<=mMax[index] )
243
    if( !InternalStackFrameList.isInitialized() || m<=mMax[index] )
243 244
      {
244 245
      mMax[index] = m<0 ? 0:m;
245 246
      return true;
src/main/java/org/distorted/library/main/DistortedFramebuffer.java
236 236
///////////////////////////////////////////////////////////////////////////////////////////////////
237 237
// create a multi-framebuffer (1 object containing multiple FBOs)
238 238

  
239
  DistortedFramebuffer(int numfbos, int numcolors, int depthStencil, int type, int width, int height)
239
  DistortedFramebuffer(int numfbos, int numcolors, int depthStencil, int type, int storage, int width, int height)
240 240
    {
241
    super(width,height,NOT_CREATED_YET,numfbos,numcolors,depthStencil,NOT_CREATED_YET, type);
241
    super(width,height,NOT_CREATED_YET,numfbos,numcolors,depthStencil,NOT_CREATED_YET, type, storage);
242 242
    markForCreation();
243 243
    }
244 244

  
......
250 250

  
251 251
  DistortedFramebuffer(int numcolors, int depthStencil, int type, int width, int height)
252 252
    {
253
    this(1,numcolors,depthStencil,type,width,height);
253
    this(1,numcolors,depthStencil,type,STORAGE_PRIVATE,width,height);
254 254
    }
255 255

  
256 256
///////////////////////////////////////////////////////////////////////////////////////////////////
......
268 268
  @SuppressWarnings("unused")
269 269
  public DistortedFramebuffer(int width, int height, int numcolors, int depthStencil)
270 270
    {
271
    this(1,numcolors,depthStencil,TYPE_USER,width,height);
271
    this(1,numcolors,depthStencil,TYPE_USER,STORAGE_PRIVATE,width,height);
272 272
    }
273 273

  
274 274
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/main/DistortedLibrary.java
57 57
 */
58 58
public class DistortedLibrary
59 59
  {
60
  private static int mGLSL;
61
  private static String mGLSL_VERSION;
62
  private static boolean mOITCompilationAttempted;
63 60
  /**
64 61
   * When creating an instance of a DistortedTexture from another instance, clone the Bitmap that's
65 62
   * backing up our DistortedTexture.
......
116 113
   * https://community.arm.com/graphics/f/discussions/10285/opengl-es-3-1-on-mali-t880-flashes
117 114
   */
118 115
  private static int mFBOQueueSize;
119

  
120
  private static boolean mInitialized=false;
116
  private static int mGLSL;
117
  private static String mGLSL_VERSION;
118
  private static boolean mOITCompilationAttempted;
119
  private static int mMaxTextureSize;
121 120

  
122 121
  //////////////////////////////////////////////////////////////////////////////////////////////
123 122
  /// MAIN PROGRAM ///
......
221 220

  
222 221
  private static ExceptionListener mListener;
223 222
  private static Resources mResources;
224
  private static int mMaxTextureSize;
225 223

  
226 224
///////////////////////////////////////////////////////////////////////////////////////////////////
227 225
// private: hide this from Javadoc
......
937 935
    return mGLSL;
938 936
    }
939 937

  
940
///////////////////////////////////////////////////////////////////////////////////////////////////
941
/**
942
 * Have we called onCreate yet, ie have we initialized the library?
943
 * @return <code>true</code> if the library is initialized and ready for action.
944
 */
945
  public static boolean isInitialized()
946
    {
947
    return mInitialized;
948
    }
949

  
950 938
///////////////////////////////////////////////////////////////////////////////////////////////////
951 939
/**
952 940
 * When OpenGL context gets created, call this method so that the library can initialise its internal data structures.
......
954 942
 * <p>
955 943
 * Needs to be called from a thread holding the OpenGL context.
956 944
 *
957
 * @param context Context of the App using the library - used to open up Resources and read Shader code.
945
 * @param context  Context of the App using the library - used to open up Resources and read Shader code.
958 946
 * @param listener The library will send all (asynchronous!) exceptions there.
959 947
 */
960 948
  public static void onSurfaceCreated(final Context context, final ExceptionListener listener)
......
969 957
 * <p>
970 958
 * Needs to be called from a thread holding the OpenGL context.
971 959
 *   
972
 * @param context Context of the App using the library - used to open up Resources and read Shader code.
973
 * @param listener The library will send all (asynchronous!) exceptions there.
960
 * @param context   Context of the App using the library - used to open up Resources and read Shader code.
961
 * @param listener  The library will send all (asynchronous!) exceptions there.
974 962
 * @param queueSize the size of the FBO queue, a workaround for the bug on Mali drivers. Use a small integer - 1,...,4
975 963
 */
976 964
  public static void onSurfaceCreated(final Context context, final ExceptionListener listener, int queueSize)
......
1002 990
    android.util.Log.e("DISTORTED", "Using OpenGL ES "+major+"."+minor);
1003 991
    mGLSL_VERSION = "#version "+mGLSL+" es\n";
1004 992

  
1005
    mInitialized = true;
993
    InternalStackFrameList.setInitialized(true);
1006 994
    mOITCompilationAttempted = false;
1007 995

  
1008 996
    detectBuggyDriversAndSetQueueSize(queueSize);
......
1038 1026
      }
1039 1027
    }
1040 1028

  
1029
///////////////////////////////////////////////////////////////////////////////////////////////////
1030
/**
1031
 * Call this so that the Library can initialize its internal data structures.
1032
 * Must be called from Activity.onCreate().
1033
 */
1034
  public static void onCreate()
1035
    {
1036
    onCreate(0);
1037
    }
1038

  
1039
///////////////////////////////////////////////////////////////////////////////////////////////////
1040
/**
1041
 * Call this so that the Library can initialize its internal data structures.
1042
 * Must be called from Activity.onCreate().
1043
 *
1044
 * @param id id of an Activity that is using the library; anything unique so that the Library can
1045
 *           tell between Activities in case you're going to be using it from more than one.
1046
 */
1047
  public static void onCreate(long id)
1048
    {
1049
    InternalStackFrameList.onCreate(id);
1050
    }
1051

  
1052
///////////////////////////////////////////////////////////////////////////////////////////////////
1053
/**
1054
 * Call this so that the Library can resume its operations.
1055
 * Must be called from Activity.onResume().
1056
 */
1057
  public static void onResume()
1058
    {
1059
    onCreate(0);
1060
    }
1061

  
1062
///////////////////////////////////////////////////////////////////////////////////////////////////
1063
/**
1064
 * Call this so that the Library can resume its operations.
1065
 * Must be called from Activity.onResume().
1066
 *
1067
 * @param id id of an Activity that is using the library; anything unique so that the Library can
1068
 *           tell between Activities in case you're going to be using it from more than one.
1069
 */
1070
  public static void onResume(long id)
1071
    {
1072
    InternalStackFrameList.onResume(id);
1073
    }
1074

  
1041 1075
///////////////////////////////////////////////////////////////////////////////////////////////////
1042 1076
/**
1043 1077
 * Call this so that the Library can release the OpenGL related data that needs to be recreated.
......
1045 1079
 */
1046 1080
  public static void onPause()
1047 1081
    {
1048
    InternalObject.onPause();
1082
    onPause(0);
1083
    }
1084

  
1085
///////////////////////////////////////////////////////////////////////////////////////////////////
1086
/**
1087
 * Call this so that the Library can release the OpenGL related data that needs to be recreated.
1088
 * Must be called from Activity.onPause().
1089
 *
1090
 * @param id id of an Activity that is using the library; anything unique so that the Library can
1091
 *           tell between Activities in case you're going to be using it from more than one.
1092
 */
1093
  public static void onPause(long id)
1094
    {
1095
    InternalStackFrameList.onPause(id);
1049 1096
    Dynamic.onPause();
1050 1097

  
1051 1098
    mLinkedListSSBO[0]= -1;
......
1061 1108
    mOITRenderProgram  = null;
1062 1109
    mBlitDepthProgram  = null;
1063 1110
    mBlitProgram       = null;
1111

  
1112

  
1113
android.util.Log.e("ON_PAUSE", "id="+id);
1064 1114
    }
1065 1115

  
1066 1116
///////////////////////////////////////////////////////////////////////////////////////////////////
1067 1117
/**
1068 1118
 * Call this so that the Library can release its internal data structures.
1069
 * Must be called from Activity.onDestroy(). 
1119
 * Must be called from Activity.onDestroy().
1070 1120
 */
1071 1121
  public static void onDestroy()
1072 1122
    {
1073
    if( mInitialized )
1123
    onDestroy(0);
1124
    }
1125

  
1126
///////////////////////////////////////////////////////////////////////////////////////////////////
1127
/**
1128
 * Call this so that the Library can release its internal data structures.
1129
 * Must be called from Activity.onDestroy().
1130
 *
1131
 * @param id id of an Activity that is using the library; anything unique so that the Library can
1132
 *           tell between Activities in case you're going to be using it from more than one.
1133
 */
1134
  public static void onDestroy(long id)
1135
    {
1136
android.util.Log.e("ON_DESTROY", "id="+id);
1137

  
1138
    if( InternalStackFrameList.isInitialized() )
1074 1139
      {
1075
      mInitialized = false;
1140
      InternalStackFrameList.setInitialized(false);
1076 1141
      mOITCompilationAttempted = false;
1077 1142

  
1078
      InternalObject.onDestroy();
1143
      InternalStackFrameList.onDestroy(id);
1079 1144
      InternalNodeData.onDestroy();
1080 1145
      InternalMaster.onDestroy();
1081 1146
      InternalOutputSurface.onDestroy();
src/main/java/org/distorted/library/main/DistortedScreen.java
80 80
 */
81 81
  public DistortedScreen()
82 82
    {
83
    super(DistortedLibrary.WAIT_FOR_FBO_QUEUE_SIZE,1,BOTH_DEPTH_STENCIL, TYPE_SYST, 1,1);
83
    super(DistortedLibrary.WAIT_FOR_FBO_QUEUE_SIZE,1,BOTH_DEPTH_STENCIL, TYPE_SYST, STORAGE_PRIVATE,1,1);
84 84
    mDebugMode = DEBUG_MODE_NONE;
85 85
    mCurRenderedFBO = 0;
86 86
    mToBeBlittedFBO = 0;
src/main/java/org/distorted/library/main/DistortedTexture.java
112 112

  
113 113
  public DistortedTexture(int type)
114 114
    {
115
    super(NOT_CREATED_YET,1,1,type);
115
    super(NOT_CREATED_YET,1,1,type,InternalObject.STORAGE_PRIVATE);
116 116
    mBmp= null;
117 117
    }
118 118

  
src/main/java/org/distorted/library/main/InternalBuffer.java
46 46

  
47 47
  public InternalBuffer(int target, int usage)
48 48
    {
49
    super(InternalObject.TYPE_USER);
49
    super(InternalObject.TYPE_USER, InternalObject.STORAGE_PRIVATE );
50 50

  
51 51
    mIndex  = new int[1];
52 52
    mTarget = target;
......
173 173
      {
174 174
      GLES30.glDeleteBuffers(1, mIndex, 0);
175 175
      mIndex[0] = -1;
176
      removeFromDone();
176 177
      }
177 178
    }
178 179

  
src/main/java/org/distorted/library/main/InternalObject.java
19 19

  
20 20
package org.distorted.library.main;
21 21

  
22
import java.util.ArrayList;
23
import java.util.HashMap;
24
import java.util.LinkedList;
25

  
26 22
///////////////////////////////////////////////////////////////////////////////////////////////////
27 23
/**
28 24
 * Any Object which gets uploaded to GPU memory and thus needs to be re-created (transparently to
......
45 41
  static final int TYPE_TREE = 1;
46 42
  static final int TYPE_SYST = 2;
47 43

  
48
  private static final int JOB_CREATE = 0;
49
  private static final int JOB_DELETE = 1;
44
  static final int STORAGE_COMMON  = 0;
45
  static final int STORAGE_PRIVATE = 1;
50 46

  
51
  private final static Object mLock = new Object();
47
  static final int JOB_CREATE = 0;
48
  static final int JOB_DELETE = 1;
52 49

  
53 50
  private long mID;
54 51
  private int mType;
55

  
56
  /////////////////////////////////////////////////////////////////
57

  
58
  private static class Job
59
    {
60
    InternalObject object;
61
    int action;
62

  
63
    Job(InternalObject o, int a)
64
      {
65
      object = o;
66
      action = a;
67
      }
68
    }
69

  
70
  /////////////////////////////////////////////////////////////////
71

  
72
  private static boolean mToDo = false;
73
  private static StackFrame mCurrentFrame = null;
74
  private static ArrayList<StackFrame> mFrameList = new ArrayList<>();
75

  
76
  /////////////////////////////////////////////////////////////////
77

  
78
  private static class StackFrame
79
    {
80
    private LinkedList<InternalObject> mDoneList;
81
    private HashMap<Long,Job> mToDoMap;
82
    private long mNextClientID;
83
    private long mNextSystemID;
84

  
85
    /////////////////////////////////////////////////////////
86

  
87
    StackFrame()
88
      {
89
      mDoneList = new LinkedList<>();
90
      mToDoMap  = new HashMap<>();
91
      mNextClientID = 0;
92
      mNextSystemID = 0;
93
      }
94

  
95
    /////////////////////////////////////////////////////////
96

  
97
    void onPause()
98
      {
99
      int num = mDoneList.size();
100

  
101
      try
102
        {
103
        for (int i=0; i<num; i++)
104
          {
105
          InternalObject object = mDoneList.removeFirst();
106
          Job job = new Job(object, JOB_CREATE);
107
          mToDoMap.put(object.mID,job);
108
          object.recreate();
109
          }
110
        }
111
      catch( Exception ignored )
112
        {
113
        // something else removed an object in the meantime; ignore
114
        }
115
      }
116

  
117
    /////////////////////////////////////////////////////////
118

  
119
    void toDo()
120
      {
121
      for(Long key: mToDoMap.keySet())
122
        {
123
        Job job = mToDoMap.get(key);
124
        InternalObject object = job.object;
125

  
126
        if( job.action==JOB_CREATE )
127
          {
128
          object.create();
129
          mDoneList.add(object);
130
          }
131
        else if( job.action==JOB_DELETE )
132
          {
133
          object.delete();
134
          }
135
        }
136

  
137
      mToDoMap.clear();
138
      }
139

  
140
    /////////////////////////////////////////////////////////
141

  
142
    long generateID(int type)
143
      {
144
      return type==TYPE_SYST ? --mNextSystemID : ++mNextClientID;
145
      }
146

  
147
    /////////////////////////////////////////////////////////
148

  
149
    void addToDoneList(InternalObject obj)
150
      {
151
      mDoneList.add(obj);
152
      }
153

  
154

  
155
    /////////////////////////////////////////////////////////
156

  
157
    void markFor(InternalObject obj, long id, int jobType)
158
      {
159
      mDoneList.remove(obj);
160
      mToDoMap.put(id, new Job(obj,jobType) );
161
      }
162

  
163
    /////////////////////////////////////////////////////////
164

  
165
    void debugLists(String frameMarker)
166
      {
167
      android.util.Log.e("Object", frameMarker);
168
      android.util.Log.e("Object", "  Done list:");
169

  
170
      for(InternalObject object : mDoneList)
171
        {
172
        object.print("  ");
173
        }
174

  
175
      android.util.Log.e("Object", "  ToDo list:");
176

  
177
      Job job;
178

  
179
      for(Long key: mToDoMap.keySet())
180
        {
181
        job = mToDoMap.get(key);
182
        job.object.print(job.action==JOB_CREATE ? " create":" delete");
183
        }
184
      }
185
    }
52
  private int mStorage;
186 53

  
187 54
///////////////////////////////////////////////////////////////////////////////////////////////////
188 55

  
......
192 59
  abstract String printDetails();
193 60

  
194 61
///////////////////////////////////////////////////////////////////////////////////////////////////
195
// must be called from a thread holding OpenGL Context
196 62

  
197
  static boolean toDo()
198
    {
199
    if( mToDo )
200
      {
201
      mToDo = false;
202

  
203
      synchronized(mLock)
204
        {
205
        mCurrentFrame.toDo();
206
        }
207
      return true;
208
      }
209

  
210
    return false;
211
    }
212

  
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

  
215
  static void onCreate()
216
    {
217
    synchronized(mLock)
218
      {
219
      mCurrentFrame = new StackFrame();
220
      mFrameList.add(mCurrentFrame);
221
      mToDo = false;
222
      }
223
    }
224

  
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

  
227
  static void onPause()
228
    {
229
    synchronized(mLock)
230
      {
231
      mCurrentFrame.onPause();
232
      mToDo = true;
233
      }
234
    }
235

  
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

  
238
  static void onDestroy()
239
    {
240
    synchronized(mLock)
241
      {
242
      int num = mFrameList.size();
243

  
244
      if( num>0 )
245
        {
246
        mFrameList.remove(num-1);
247

  
248
        if( num>1 )
249
          {
250
          mCurrentFrame = mFrameList.get(num-2);
251
          mToDo = true;
252
          }
253
        else
254
          {
255
          mCurrentFrame = null;
256
          mToDo = false;
257
          }
258
        }
259
      }
260
    }
261

  
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

  
264
  @SuppressWarnings("unused")
265
  static void debugLists()
266
    {
267
    int num = mFrameList.size();
268
    StackFrame frame;
269

  
270
    for(int i=0; i<num; i++)
271
      {
272
      frame = mFrameList.get(i);
273
      frame.debugLists("frame "+i);
274
      }
275
    }
276

  
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

  
279
  private void print(String msg)
63
  void print(String msg)
280 64
    {
281 65
    String str = "ID:"+mID;
282 66

  
......
293 77

  
294 78
///////////////////////////////////////////////////////////////////////////////////////////////////
295 79

  
296
  InternalObject(int type)
80
  InternalObject(int type, int storage)
297 81
    {
298
    if( mCurrentFrame==null ) onCreate();
299

  
300
    mID = mCurrentFrame.generateID(type);
301
    mType= type;
82
    mType    = type;
83
    mStorage = storage;
84
    mID      = InternalStackFrameList.getCurrentFrame().generateID(mType,mStorage);
302 85
    }
303 86

  
304 87
///////////////////////////////////////////////////////////////////////////////////////////////////
305 88

  
306 89
  void markWasCreatedImmediately()
307 90
    {
308
    mCurrentFrame.addToDoneList(this);
91
    InternalStackFrameList.getCurrentFrame().addToDoneList(this,mStorage);
309 92
    }
310 93

  
311 94
///////////////////////////////////////////////////////////////////////////////////////////////////
312 95

  
313 96
  void markForCreation()
314 97
    {
315
    synchronized(mLock)
316
      {
317
      mCurrentFrame.markFor(this,mID,JOB_CREATE);
318
      mToDo = true;
319
      }
98
    InternalStackFrameList.markFor(this,mID,mStorage,JOB_CREATE);
99
    }
100

  
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102

  
103
  void removeFromDone()
104
    {
105
    InternalStackFrameList.removeFromDone(this,mStorage);
320 106
    }
321 107

  
322 108
///////////////////////////////////////////////////////////////////////////////////////////////////
......
327 113
 */
328 114
  public void markForDeletion()
329 115
    {
330
    synchronized(mLock)
331
      {
332
      mCurrentFrame.markFor(this,mID,JOB_DELETE);
333
      mToDo = true;
334
      }
116
    InternalStackFrameList.markFor(this,mID,mStorage,JOB_DELETE);
335 117
    }
336 118

  
337 119
////////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/main/InternalOutputSurface.java
65 65

  
66 66
///////////////////////////////////////////////////////////////////////////////////////////////////
67 67

  
68
  InternalOutputSurface(int width, int height, int createColor, int numfbos, int numcolors, int depthStencil, int fbo, int type)
68
  InternalOutputSurface(int width, int height, int createColor, int numfbos, int numcolors, int depthStencil, int fbo, int type, int storage)
69 69
    {
70
    super(createColor,numfbos,numcolors,type);
70
    super(createColor,numfbos,numcolors,type,storage);
71 71

  
72 72
    mRenderWayOIT = false;
73 73
    mCurrFBO      = 0;
......
179 179

  
180 180
    for (int j=0; j<quality; j++) mipmap *= EffectQuality.MULTIPLIER;
181 181

  
182
    mBuffer[quality] = new DistortedFramebuffer(queueSize,2,BOTH_DEPTH_STENCIL,TYPE_SYST, (int)(width*mipmap), (int)(height*mipmap) );
182
    mBuffer[quality] = new DistortedFramebuffer(queueSize,2,BOTH_DEPTH_STENCIL,TYPE_SYST, STORAGE_COMMON, (int)(width*mipmap), (int)(height*mipmap) );
183 183
    mBuffer[quality].mMipmap = mipmap;
184 184
    mBuffer[quality].mNear = near;  // copy mNear as well (for blitting- see PostprocessEffect.apply() )
185 185
    mBuffer[quality].glClearColor(CLEAR_R, CLEAR_G, CLEAR_B, CLEAR_A);
186 186

  
187
    InternalObject.toDo(); // create the FBOs immediately. This is safe as we must be holding the OpenGL context now.
187
    InternalStackFrameList.toDo(); // create the FBOs immediately. This is safe as we must be holding the OpenGL context now.
188 188

  
189 189
    InternalRenderState.colorDepthStencilOn();
190 190
    GLES30.glClearColor(CLEAR_R, CLEAR_G, CLEAR_B, CLEAR_A);
......
609 609
  public int render(long time, int fbo)
610 610
    {
611 611
    InternalMaster.toDo();
612
    toDo();
612
    InternalStackFrameList.toDo();
613 613
    InternalRenderState.reset();
614 614

  
615 615
    int numRenders=0, numChildren = mChildren.getNumChildren();
src/main/java/org/distorted/library/main/InternalStackFrame.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
package org.distorted.library.main;
21

  
22
import java.util.HashMap;
23
import java.util.LinkedList;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

  
27
public class InternalStackFrame
28
{
29
  private static class Job
30
    {
31
    InternalObject object;
32
    int action;
33

  
34
    Job(InternalObject o, int a)
35
      {
36
      object = o;
37
      action = a;
38
      }
39
    }
40

  
41
  private static LinkedList<InternalObject> mCommonDoneList = new LinkedList<>(); //
42
  private static HashMap<Long,Job> mCommonToDoMap           = new HashMap<>();    // Common
43
  private static long mCommonNextClientID                   = 0;                  // InternalObject
44
  private static long mCommonNextSystemID                   = 0;                  // (postprocessing)
45

  
46
  private LinkedList<InternalObject> mDoneList; //
47
  private HashMap<Long,Job> mToDoMap;           //
48
  private long mNextClientID;                   // InternalObject
49
  private long mNextSystemID;                   //
50
  private long mTaskId;                         //
51

  
52
  private static boolean mInitialized;          // DistortedLibrary
53

  
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

  
56
  InternalStackFrame(long taskID)
57
    {
58
    mDoneList     = new LinkedList<>();
59
    mToDoMap      = new HashMap<>();
60
    mNextClientID = 0;
61
    mNextSystemID = 0;
62
    mTaskId       = taskID;
63
    }
64

  
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

  
67
  long getTaskId()
68
    {
69
    return mTaskId;
70
    }
71

  
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

  
74
  static void onPauseCommon()
75
    {
76
    onPauseGeneric(mCommonDoneList,mCommonToDoMap);
77
    }
78

  
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80

  
81
  void onPause()
82
    {
83
    onPauseGeneric(mDoneList,mToDoMap);
84
    }
85

  
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

  
88
  static void onPauseGeneric(LinkedList<InternalObject> list, HashMap<Long,Job> map)
89
    {
90
    int num = list.size();
91

  
92
    try
93
      {
94
      for (int i=0; i<num; i++)
95
        {
96
        InternalObject object = list.removeFirst();
97
        Job job = new Job(object, InternalObject.JOB_CREATE);
98
        map.put(object.getID(),job);
99
        object.recreate();
100
        }
101
      }
102
    catch( Exception ignored )
103
      {
104
      // something else removed an object in the meantime; ignore
105
      }
106
    }
107

  
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

  
110
  void toDo()
111
    {
112
    toDoGeneric(mDoneList,mToDoMap);
113
    }
114

  
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116

  
117
  static void toDoCommon()
118
    {
119
    toDoGeneric(mCommonDoneList,mCommonToDoMap);
120
    }
121

  
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

  
124
  static void toDoGeneric(LinkedList<InternalObject> list, HashMap<Long,Job> map)
125
    {
126
    for(Long key: map.keySet())
127
      {
128
      Job job = map.get(key);
129
      InternalObject object = job.object;
130

  
131
      if( job.action==InternalObject.JOB_CREATE )
132
        {
133
        object.create();
134
        list.add(object);
135
        }
136
      else if( job.action==InternalObject.JOB_DELETE )
137
        {
138
        object.delete();
139
        }
140
      }
141

  
142
    map.clear();
143
    }
144

  
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

  
147
  static void cleanCommon()
148
    {
149
    mCommonDoneList.clear();
150
    mCommonToDoMap.clear();
151
    mCommonNextClientID = 0;
152
    mCommonNextSystemID = 0;
153
    }
154

  
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

  
157
  long generateID(int type, int storage)
158
    {
159
    if( storage==InternalObject.STORAGE_PRIVATE )
160
      {
161
      return type==InternalObject.TYPE_SYST ? --mNextSystemID : ++mNextClientID;
162
      }
163
    else
164
      {
165
      return type==InternalObject.TYPE_SYST ? --mCommonNextSystemID : ++mCommonNextClientID;
166
      }
167
    }
168

  
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

  
171
  void addToDoneList(InternalObject obj, int storage)
172
    {
173
    if( storage==InternalObject.STORAGE_PRIVATE )
174
      {
175
      if( !mDoneList.contains(obj) )
176
        {
177
        mDoneList.add(obj);
178
        }
179
      }
180
    else
181
      {
182
      if( !mCommonDoneList.contains(obj) ) mCommonDoneList.add(obj);
183
      }
184
    }
185

  
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

  
188
  void removeFromDoneList(InternalObject obj, int storage)
189
    {
190
    if( storage==InternalObject.STORAGE_PRIVATE )
191
      {
192
      mDoneList.remove(obj);
193
      }
194
    else
195
      {
196
      mCommonDoneList.remove(obj);
197
      }
198
    }
199

  
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

  
202
  void markFor(InternalObject obj, long id, int storage, int jobType)
203
    {
204
    if( storage==InternalObject.STORAGE_PRIVATE )
205
      {
206
      mDoneList.remove(obj);
207
      mToDoMap.put(id, new Job(obj,jobType) );
208
      }
209
    else
210
      {
211
      mCommonDoneList.remove(obj);
212
      mCommonToDoMap.put(id, new Job(obj,jobType) );
213
      }
214
    }
215

  
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

  
218
  boolean isInitialized()
219
    {
220
    return mInitialized;
221
    }
222

  
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

  
225
  void setInitialized(boolean init)
226
    {
227
    mInitialized = init;
228
    }
229

  
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

  
232
  void debugLists(String frameMarker)
233
    {
234
    debugListsGeneric(mDoneList,mToDoMap,frameMarker);
235
    }
236

  
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

  
239
  static void debugCommonList()
240
    {
241
    debugListsGeneric(mCommonDoneList,mCommonToDoMap,"Common");
242
    }
243

  
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

  
246
  static void debugListsGeneric(LinkedList<InternalObject> list, HashMap<Long,Job> map,String frameMarker)
247
    {
248
    android.util.Log.e("Object", frameMarker);
249
    android.util.Log.e("Object", "  Done list:");
250

  
251
    for(InternalObject object : list)
252
      {
253
      object.print("  ");
254
      }
255

  
256
    android.util.Log.e("Object", "  ToDo list:");
257

  
258
    Job job;
259

  
260
    for(Long key: map.keySet())
261
      {
262
      job = map.get(key);
263
      job.object.print(job.action==InternalObject.JOB_CREATE ? " create":" delete");
264
      }
265
    }
266
  }
src/main/java/org/distorted/library/main/InternalStackFrameList.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
package org.distorted.library.main;
21

  
22
import java.util.ArrayList;
23

  
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

  
26
public class InternalStackFrameList
27
{
28
  private final static Object mLock = new Object();
29
  private static boolean mToDo = false;
30
  private static InternalStackFrame mCurrentFrame = null;
31
  private static ArrayList<InternalStackFrame> mFrameList = new ArrayList<>();
32

  
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34

  
35
  static void onCreate(long taskId)
36
    {
37
    int num = mFrameList.size();
38
    InternalStackFrame frame;
39
    boolean found = false;
40

  
41
    for(int i=0; i<num; i++)
42
      {
43
      frame = mFrameList.get(i);
44

  
45
      if( frame.getTaskId() == taskId )
46
        {
47
        mCurrentFrame = frame;
48
        found = true;
49
        break;
50
        }
51
      }
52

  
53
    if( !found )
54
      {
55
      synchronized(mLock)
56
        {
57
        mCurrentFrame = new InternalStackFrame(taskId);
58
        mFrameList.add(mCurrentFrame);
59
        }
60
      }
61

  
62
    mCurrentFrame.setInitialized(false);
63
    }
64

  
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

  
67
  static void onResume(long taskId)
68
    {
69
    int num = mFrameList.size();
70
    InternalStackFrame frame;
71

  
72
    for(int i=0; i<num; i++)
73
      {
74
      frame = mFrameList.get(i);
75

  
76
      if( frame.getTaskId() == taskId )
77
        {
78
        mCurrentFrame = frame;
79
        break;
80
        }
81
      }
82

  
83
    mCurrentFrame.setInitialized(false);
84
    }
85

  
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

  
88
  static void onPause(long taskId)
89
    {
90
    int num = mFrameList.size();
91

  
92
    for(int i=0; i<num; i++)
93
      {
94
      if( mFrameList.get(i).getTaskId() == taskId )
95
        {
96
        synchronized(mLock)
97
          {
98
          mCurrentFrame.onPause();
99
          InternalStackFrame.onPauseCommon();
100
          mToDo = true;
101
          }
102

  
103
        break;
104
        }
105
      }
106
    }
107

  
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

  
110
  static void onDestroy(long taskId)
111
    {
112
    int num = mFrameList.size();
113

  
114
    for(int i=0; i<num; i++)
115
      {
116
      if( mFrameList.get(i).getTaskId() == taskId )
117
        {
118
        synchronized(mLock)
119
          {
120
          mFrameList.remove(i);
121
          if( num==1 ) InternalStackFrame.cleanCommon();
122
          }
123

  
124
        break;
125
        }
126
      }
127
    }
128

  
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

  
131
  @SuppressWarnings("unused")
132
  static void debugLists()
133
    {
134
    int num = mFrameList.size();
135
    InternalStackFrame frame;
136

  
137
    InternalStackFrame.debugCommonList();
138

  
139
    for(int i=0; i<num; i++)
140
      {
141
      frame = mFrameList.get(i);
142
      frame.debugLists("frame "+i);
143
      }
144
    }
145

  
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147
// must be called from a thread holding OpenGL Context
148

  
149
  static boolean toDo()
150
    {
151
    if( mToDo )
152
      {
153
      mToDo = false;
154

  
155
      synchronized(mLock)
156
        {
157
        mCurrentFrame.toDo();
158
        InternalStackFrame.toDoCommon();
159
        }
160
      return true;
161
      }
162

  
163
    return false;
164
    }
165

  
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

  
168
  static void markFor(InternalObject obj, long id, int storage, int job)
169
    {
170
    synchronized(mLock)
171
      {
172
      mCurrentFrame.markFor(obj,id,storage,job);
173
      mToDo = true;
174
      }
175
    }
176

  
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

  
179
  static void removeFromDone(InternalObject obj, int storage)
180
    {
181
    synchronized(mLock)
182
      {
183
      mCurrentFrame.removeFromDoneList(obj,storage);
184
      }
185
    }
186

  
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

  
189
  static InternalStackFrame getCurrentFrame()
190
    {
191
    return mCurrentFrame;
192
    }
193

  
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

  
196
  static void setInitialized(boolean init)
197
    {
198
    mCurrentFrame.setInitialized(init);
199
    }
200

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
// PUBLIC API
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

  
205
  public static boolean isInitialized()
206
    {
207
    return mCurrentFrame.isInitialized();
208
    }
209

  
210
}
src/main/java/org/distorted/library/main/InternalSurface.java
33 33

  
34 34
///////////////////////////////////////////////////////////////////////////////////////////////////
35 35

  
36
  InternalSurface(int create, int numfbos, int numcolors, int type)
36
  InternalSurface(int create, int numfbos, int numcolors, int type, int storage)
37 37
    {
38
    super(type);
38
    super(type,storage);
39 39

  
40 40
    mNumFBOs      = numfbos;
41 41
    mNumColors    = numcolors;

Also available in: Unified diff