Project

General

Profile

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

library / src / main / java / org / distorted / library / main / InternalObject.java @ 246d021c

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 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
 * Any Object which gets uploaded to GPU memory and thus needs to be re-created (transparently to
28
 * applications!) whenever we lose OpenGL context.
29
 *
30
 * Keep all objects created in a static LinkedList. The point: we need to be able to mark
31
 * Objects for deletion, and delete all marked Objects later at a convenient time (that's
32
 * because we can only delete from a thread that holds the OpenGL context so here we provide a
33
 * framework where one is able to mark for deletion at any time and actual deletion takes place
34
 * on the next render).
35
*/
36
abstract class InternalObject
37
{
38
  static final int FAILED_TO_CREATE = 1;
39
  static final int NOT_CREATED_YET  = 2;
40
  static final int DONT_CREATE      = 3;
41
  static final int CREATED          = 4;
42

    
43
  static final int TYPE_USER = 0;
44
  static final int TYPE_TREE = 1;
45
  static final int TYPE_SYST = 2;
46

    
47
  private static final int JOB_CREATE = 0;
48
  private static final int JOB_DELETE = 1;
49

    
50
  private static class Job
51
    {
52
    InternalObject object;
53
    int action;
54

    
55
    Job(InternalObject o, int a)
56
      {
57
      object = o;
58
      action = a;
59
      }
60
    }
61

    
62
  private static boolean mToDo = false;
63
  private static LinkedList<InternalObject> mDoneList = new LinkedList<>();
64
  private static HashMap<Long,Job> mToDoMap = new HashMap<>();
65
  private static long mNextClientID = 0;
66
  private static long mNextSystemID = 0;
67

    
68
  private final static Object mDoneLock = new Object();
69
  private final static Object mToDoLock = new Object();
70

    
71
  private long mID;
72
  private int mType;
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

    
76
  abstract void create();
77
  abstract void delete();
78
  abstract void recreate();
79
  abstract String printDetails();
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82
// must be called from a thread holding OpenGL Context
83

    
84
  static boolean toDo()
85
    {
86
    if( mToDo )
87
      {
88
      Job job;
89
      InternalObject object;
90

    
91
      synchronized(mToDoLock)
92
        {
93
        for(Long key: mToDoMap.keySet())
94
          {
95
          job = mToDoMap.get(key);
96
          object = job.object;
97

    
98
          if( job.action==JOB_CREATE )
99
            {
100
            object.create();
101
            mDoneList.add(object);
102
            }
103
          else if( job.action==JOB_DELETE )
104
            {
105
            object.delete();
106
            }
107
          }
108

    
109
        mToDoMap.clear();
110
        mToDo = false;
111
        }
112

    
113
      return true;
114
      }
115

    
116
    return false;
117
    }
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

    
121
  static void onPause()
122
    {
123
    InternalObject object;
124

    
125
    synchronized(mDoneLock)
126
      {
127
      synchronized(mToDoLock)
128
        {
129
        int num = mDoneList.size();
130

    
131
        try
132
          {
133
          for (int i = 0; i < num; i++)
134
            {
135
            object = mDoneList.removeFirst();
136
            Job job = new Job(object, JOB_CREATE);
137
            mToDoMap.put(object.mID,job);
138
            object.recreate();
139
            }
140
          }
141
        catch( Exception ex )
142
          {
143
          // something else removed an object in the meantime; ignore
144
          }
145
        }
146
      }
147

    
148
    mToDo = true;
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152

    
153
  static void onDestroy()
154
    {
155
    synchronized(mToDoLock)
156
      {
157
      synchronized(mDoneLock)
158
        {
159
        mToDoMap.clear();
160
        mDoneList.clear();
161

    
162
        mToDo = true;
163
        mNextClientID = 0;
164
        }
165
      }
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

    
170
  @SuppressWarnings("unused")
171
  static void debugLists()
172
    {
173
    android.util.Log.e("Object", "Done list:");
174

    
175
    for(InternalObject object : mDoneList)
176
      {
177
      object.print("");
178
      }
179

    
180
    android.util.Log.e("Object", "ToDo list:");
181

    
182
    Job job;
183

    
184
    for(Long key: mToDoMap.keySet())
185
      {
186
      job = mToDoMap.get(key);
187
      job.object.print(job.action==JOB_CREATE ? " create":" delete");
188
      }
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
  private void print(String msg)
194
    {
195
    String str = "ID:"+mID;
196

    
197
    switch(mType)
198
      {
199
      case TYPE_SYST: str+=" SYSTEM "; break;
200
      case TYPE_USER: str+=" USER   "; break;
201
      case TYPE_TREE: str+=" TREE   "; break;
202
      default       : str+=" ERROR? ";
203
      }
204

    
205
    android.util.Log.e("Object", str+printDetails()+msg);
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  InternalObject(int type)
211
    {
212
    mID  = type==TYPE_SYST ? --mNextSystemID : ++mNextClientID;
213
    mType= type;
214
    }
215

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

    
218
  void markWasCreatedImmediately()
219
    {
220
    mDoneList.add(this);
221
    }
222

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

    
225
  void markForCreation()
226
    {
227
    synchronized(mDoneLock)
228
      {
229
      mDoneList.remove(this);
230
      }
231

    
232
    synchronized(mToDoLock)
233
      {
234
      mToDoMap.put(mID, new Job(this,JOB_CREATE) );
235
      mToDo = true;
236
      }
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
// PUBLIC API
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242
/**
243
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
244
 */
245
  public void markForDeletion()
246
    {
247
    synchronized(mDoneLock)
248
      {
249
      mDoneList.remove(this);
250
      }
251

    
252
    synchronized(mToDoLock)
253
      {
254
      mToDoMap.put(mID, new Job(this,JOB_DELETE) );
255
      mToDo = true;
256
      }
257
    }
258

    
259
////////////////////////////////////////////////////////////////////////////////////////////////////
260
/**
261
 * Return unique ID of this Object.
262
 */
263
  public long getID()
264
    {
265
    return mID;
266
    }
267

    
268
}
(11-11/14)