Project

General

Profile

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

library / src / main / java / org / distorted / library / main / InternalObject.java @ b7074bc6

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 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
            mToDoMap.put(object.mID, object.new Job(object, JOB_CREATE));
137
            object.recreate();
138
            }
139
          }
140
        catch( Exception ex )
141
          {
142
          // something else removed an object in the meantime; ignore
143
          }
144
        }
145
      }
146

    
147
    mToDo = true;
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

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

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

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

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

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

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

    
181
    Job job;
182

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

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

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

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

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

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

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

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

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

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

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

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

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

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

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

    
267
}
(11-11/14)