Project

General

Profile

Download (9.6 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / main / InternalObject.java @ 9519d1b1

1 226144d0 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4 46b572b5 Leszek Koltunski
// This file is part of Distorted.                                                               //
5 226144d0 leszek
//                                                                                               //
6 46b572b5 Leszek Koltunski
// Distorted is free software: you can redistribute it and/or modify                             //
7 226144d0 leszek
// 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 46b572b5 Leszek Koltunski
// Distorted is distributed in the hope that it will be useful,                                  //
12 226144d0 leszek
// 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 46b572b5 Leszek Koltunski
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18 226144d0 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 fe82a979 Leszek Koltunski
package org.distorted.library.main;
21 226144d0 leszek
22 9519d1b1 Leszek Koltunski
import java.util.ArrayList;
23 226144d0 leszek
import java.util.HashMap;
24
import java.util.LinkedList;
25
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27
/**
28
 * Any Object which gets uploaded to GPU memory and thus needs to be re-created (transparently to
29
 * applications!) whenever we lose OpenGL context.
30
 *
31
 * Keep all objects created in a static LinkedList. The point: we need to be able to mark
32
 * Objects for deletion, and delete all marked Objects later at a convenient time (that's
33
 * because we can only delete from a thread that holds the OpenGL context so here we provide a
34
 * framework where one is able to mark for deletion at any time and actual deletion takes place
35
 * on the next render).
36
*/
37 7602a827 Leszek Koltunski
abstract class InternalObject
38 226144d0 leszek
{
39
  static final int FAILED_TO_CREATE = 1;
40
  static final int NOT_CREATED_YET  = 2;
41
  static final int DONT_CREATE      = 3;
42
  static final int CREATED          = 4;
43
44
  static final int TYPE_USER = 0;
45
  static final int TYPE_TREE = 1;
46
  static final int TYPE_SYST = 2;
47
48
  private static final int JOB_CREATE = 0;
49
  private static final int JOB_DELETE = 1;
50
51 9519d1b1 Leszek Koltunski
  private final static Object mLock = new Object();
52
53
  private long mID;
54
  private int mType;
55
56
  /////////////////////////////////////////////////////////////////
57
58 f0604575 Leszek Koltunski
  private static class Job
59 226144d0 leszek
    {
60 7602a827 Leszek Koltunski
    InternalObject object;
61 226144d0 leszek
    int action;
62
63 7602a827 Leszek Koltunski
    Job(InternalObject o, int a)
64 226144d0 leszek
      {
65
      object = o;
66
      action = a;
67
      }
68
    }
69
70 9519d1b1 Leszek Koltunski
  /////////////////////////////////////////////////////////////////
71
72 226144d0 leszek
  private static boolean mToDo = false;
73 9519d1b1 Leszek Koltunski
  private static StackFrame mCurrentFrame = null;
74
  private static ArrayList<StackFrame> mFrameList = new ArrayList<>();
75 226144d0 leszek
76 9519d1b1 Leszek Koltunski
  /////////////////////////////////////////////////////////////////
77 d2039fdd Leszek Koltunski
78 9519d1b1 Leszek Koltunski
  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
    }
186 226144d0 leszek
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188
189
  abstract void create();
190
  abstract void delete();
191
  abstract void recreate();
192
  abstract String printDetails();
193
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195
// must be called from a thread holding OpenGL Context
196
197 d2039fdd Leszek Koltunski
  static boolean toDo()
198 226144d0 leszek
    {
199
    if( mToDo )
200
      {
201 9519d1b1 Leszek Koltunski
      mToDo = false;
202 226144d0 leszek
203 9519d1b1 Leszek Koltunski
      synchronized(mLock)
204 226144d0 leszek
        {
205 9519d1b1 Leszek Koltunski
        mCurrentFrame.toDo();
206 226144d0 leszek
        }
207
      return true;
208
      }
209
210
    return false;
211
    }
212
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214
215 9519d1b1 Leszek Koltunski
  static void onCreate()
216 226144d0 leszek
    {
217 9519d1b1 Leszek Koltunski
    synchronized(mLock)
218 040cd18c Leszek Koltunski
      {
219 9519d1b1 Leszek Koltunski
      mCurrentFrame = new StackFrame();
220
      mFrameList.add(mCurrentFrame);
221
      mToDo = false;
222 040cd18c Leszek Koltunski
      }
223 9519d1b1 Leszek Koltunski
    }
224
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226 226144d0 leszek
227 9519d1b1 Leszek Koltunski
  static void onPause()
228
    {
229
    synchronized(mLock)
230
      {
231
      mCurrentFrame.onPause();
232
      mToDo = true;
233
      }
234 226144d0 leszek
    }
235
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
238 d2039fdd Leszek Koltunski
  static void onDestroy()
239 226144d0 leszek
    {
240 9519d1b1 Leszek Koltunski
    synchronized(mLock)
241 d2039fdd Leszek Koltunski
      {
242 9519d1b1 Leszek Koltunski
      int num = mFrameList.size();
243
244
      if( num>0 )
245 d2039fdd Leszek Koltunski
        {
246 9519d1b1 Leszek Koltunski
        mFrameList.remove(num-1);
247 226144d0 leszek
248 9519d1b1 Leszek Koltunski
        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 d2039fdd Leszek Koltunski
        }
259
      }
260 226144d0 leszek
    }
261
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263
264
  @SuppressWarnings("unused")
265
  static void debugLists()
266
    {
267 9519d1b1 Leszek Koltunski
    int num = mFrameList.size();
268
    StackFrame frame;
269 226144d0 leszek
270 9519d1b1 Leszek Koltunski
    for(int i=0; i<num; i++)
271 226144d0 leszek
      {
272 9519d1b1 Leszek Koltunski
      frame = mFrameList.get(i);
273
      frame.debugLists("frame "+i);
274 226144d0 leszek
      }
275
    }
276
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278
279
  private void print(String msg)
280
    {
281
    String str = "ID:"+mID;
282
283
    switch(mType)
284
      {
285
      case TYPE_SYST: str+=" SYSTEM "; break;
286
      case TYPE_USER: str+=" USER   "; break;
287
      case TYPE_TREE: str+=" TREE   "; break;
288
      default       : str+=" ERROR? ";
289
      }
290
291
    android.util.Log.e("Object", str+printDetails()+msg);
292
    }
293
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295
296 7602a827 Leszek Koltunski
  InternalObject(int type)
297 226144d0 leszek
    {
298 9519d1b1 Leszek Koltunski
    if( mCurrentFrame==null ) onCreate();
299
300
    mID = mCurrentFrame.generateID(type);
301 226144d0 leszek
    mType= type;
302
    }
303
304 22e60fba Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
305
306
  void markWasCreatedImmediately()
307
    {
308 9519d1b1 Leszek Koltunski
    mCurrentFrame.addToDoneList(this);
309 22e60fba Leszek Koltunski
    }
310
311 226144d0 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
312
313 d2039fdd Leszek Koltunski
  void markForCreation()
314 226144d0 leszek
    {
315 9519d1b1 Leszek Koltunski
    synchronized(mLock)
316 d2039fdd Leszek Koltunski
      {
317 9519d1b1 Leszek Koltunski
      mCurrentFrame.markFor(this,mID,JOB_CREATE);
318 d2039fdd Leszek Koltunski
      mToDo = true;
319
      }
320 226144d0 leszek
    }
321
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323
// PUBLIC API
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325
/**
326
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
327
 */
328 d2039fdd Leszek Koltunski
  public void markForDeletion()
329 226144d0 leszek
    {
330 9519d1b1 Leszek Koltunski
    synchronized(mLock)
331 d2039fdd Leszek Koltunski
      {
332 9519d1b1 Leszek Koltunski
      mCurrentFrame.markFor(this,mID,JOB_DELETE);
333 d2039fdd Leszek Koltunski
      mToDo = true;
334
      }
335 226144d0 leszek
    }
336
337
////////////////////////////////////////////////////////////////////////////////////////////////////
338
/**
339
 * Return unique ID of this Object.
340
 */
341
  public long getID()
342
    {
343
    return mID;
344
    }
345
}