Project

General

Profile

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

library / src / main / java / org / distorted / library / main / EffectQueue.java @ fe82a979

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 org.distorted.library.effect.Effect;
23
import org.distorted.library.message.EffectListener;
24
import org.distorted.library.message.EffectMessage;
25
import org.distorted.library.type.Dynamic;
26

    
27
import java.util.Vector;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

    
31
abstract class EffectQueue
32
  {
33
  protected byte mNumEffects;   // number of effects at the moment
34
  protected long mTotalEffects; // total number of effects ever created
35
  protected int[] mName;
36
  protected int[] mType;
37
  protected float[] mUniforms;
38
  protected float[] mCache;
39
  protected Dynamic[][] mInter;
40
  protected long[] mCurrentDuration;
41
  protected byte[] mFreeIndexes;
42
  protected byte[] mIDIndex;
43
  protected long[] mID;
44
  protected long mTime=0;
45
  protected static int[] mMax = new int[Effect.LENGTH];
46
  protected int mMaxIndex;
47
  protected Vector<EffectListener> mListeners =null;
48
  protected int mNumListeners=0;  // ==mListeners.length(), but we only create mListeners if the first one gets added
49
  protected long mObjectID;
50

    
51
  private static boolean mCreated;
52

    
53
  static
54
    {
55
    onDestroy();
56
    }
57
  
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59
   
60
  EffectQueue(long id, int numUniforms, int numCache, int index)
61
    {
62
    mNumEffects   = 0;
63
    mTotalEffects = 0;
64
    mMaxIndex     = index;
65
    mObjectID     = id;
66

    
67
    int max = mMax[mMaxIndex];
68

    
69
    if( max>0 )
70
      {
71
      mName            = new int[max];
72
      mType            = new int[max];
73
      mUniforms        = new float[numUniforms*max];
74
      mInter           = new Dynamic[3][max];
75
      mCurrentDuration = new long[max];
76
      mID              = new long[max];
77
      mIDIndex         = new byte[max];
78
      mFreeIndexes     = new byte[max];
79
     
80
      for(byte i=0; i<max; i++) mFreeIndexes[i] = i;
81

    
82
      if( numCache>0 )
83
        {
84
        mCache = new float[numCache*max];
85
        }
86
      }
87
   
88
    mCreated = true;  
89
    }
90

    
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

    
93
  @SuppressWarnings("unused")
94
  int getNumEffects()
95
    {
96
    return mNumEffects;  
97
    }
98

    
99
///////////////////////////////////////////////////////////////////////////////////////////////////
100
// Only max Byte.MAX_VALUE concurrent effects per DistortedEffects object.
101
// If you want more, change type of the mNumEffects, mIDIndex and mFreeIndexes variables to shorts.
102
// (although probably this many uniforms will not fit in the shaders anyway!)
103

    
104
  static boolean setMax(int index, int m)
105
    {
106
    if( (!mCreated && !Distorted.isInitialized()) || m<=mMax[index] )
107
      {
108
      if( m<0              ) m = 0;
109
      else if( m>Byte.MAX_VALUE ) m = Byte.MAX_VALUE;
110

    
111
      mMax[index] = m;
112
      return true;
113
      }
114

    
115
    return false;
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119

    
120
  static int getMax(int index)
121
    {
122
    return mMax[index];
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

    
127
  void registerForMessages(EffectListener el)
128
    {
129
    if( mListeners==null ) mListeners = new Vector<>(2,2);
130

    
131
    if( !mListeners.contains(el) )
132
      {
133
      mListeners.add(el);
134
      mNumListeners++;
135
      }
136
    }
137
 
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  void deregisterForMessages(EffectListener el)
141
    {
142
    if( mListeners.remove(el) )
143
      {
144
      mNumListeners--;
145
      }
146
    }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

    
150
  static void onDestroy()
151
    {
152
    Effect.reset(mMax);
153
    mCreated = false;  
154
    }
155
 
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
  synchronized int removeByID(long id)
159
    {
160
    int i = getEffectIndex(id);
161
   
162
    if( i>=0 ) 
163
      {
164
      remove(i);
165
      return 1;
166
      }
167
   
168
    return 0;
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  synchronized int removeByType(Effect effect)
174
    {
175
    int ret  = 0;
176
    int name = effect.getName();
177
    int type = effect.getType();
178

    
179
    for(int i=0; i<mNumEffects; i++)
180
      {
181
      if( mName[i]==name && mType[i]==type )
182
        {
183
        remove(i);
184
        i--;
185
        ret++;
186
        }
187
      }
188
   
189
    return ret;
190
    }
191
  
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193
  
194
  private synchronized int getEffectIndex(long id)
195
    {
196
    int index = mIDIndex[(int)(id%mMax[mMaxIndex])];
197
    return (index<mNumEffects && mID[index]==id ? index : -1);
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201
// we do want to notify Listeners if they called 'abortAll' themselves but don't want to notify
202
// them if it is the library itself which is releasing resources.
203

    
204
  synchronized int abortAll(boolean notify)
205
    {
206
    int ret = mNumEffects;
207
    long removedID;
208
    int removedName, removedType;
209

    
210
    for(int i=0; i<ret; i++ )
211
      {
212
      mInter[0][i] = null;
213
      mInter[1][i] = null;
214
      mInter[2][i] = null;
215

    
216
      if( notify )
217
        {
218
        removedID = mID[i];
219
        removedName= mName[i];
220
        removedType= mType[i];
221

    
222
        for(int j=0; j<mNumListeners; j++)
223
          EffectMessageSender.newMessage( mListeners.elementAt(j),
224
                                          EffectMessage.EFFECT_REMOVED,
225
                                          (removedID<<Effect.LENGTH)+removedType,
226
                                          removedName,
227
                                          mObjectID);
228
        }
229
      }
230

    
231
    mNumEffects= 0;
232

    
233
    return ret;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// this assumes 0<=effect<mNumEffects
238
  
239
  protected void remove(int effect)
240
    {
241
    mNumEffects--;     
242
    
243
    byte removedIndex = (byte)(mID[effect]%mMax[mMaxIndex]);
244
    byte removedPosition = mIDIndex[removedIndex];
245
    mFreeIndexes[mNumEffects] = removedIndex;
246
    
247
    long removedID = mID[effect];
248
    int removedName= mName[effect];
249
    int removedType= mType[effect];
250

    
251
    for(int j=0; j<mMax[mMaxIndex]; j++)
252
      {
253
      if( mIDIndex[j] > removedPosition ) mIDIndex[j]--; 
254
      }
255
         
256
    for(int j=effect; j<mNumEffects; j++ ) 
257
      {
258
      mName[j]            = mName[j+1];
259
      mType[j]            = mType[j+1];
260
      mInter[0][j]        = mInter[0][j+1];
261
      mInter[1][j]        = mInter[1][j+1];
262
      mInter[2][j]        = mInter[2][j+1];
263
      mCurrentDuration[j] = mCurrentDuration[j+1];
264
      mID[j]              = mID[j+1];
265
    
266
      moveEffect(j);
267
      }
268
   
269
    mInter[0][mNumEffects] = null;
270
    mInter[1][mNumEffects] = null;
271
    mInter[2][mNumEffects] = null;
272

    
273
    for(int i=0; i<mNumListeners; i++) 
274
      EffectMessageSender.newMessage( mListeners.elementAt(i),
275
                                      EffectMessage.EFFECT_REMOVED,
276
                                      (removedID<<Effect.LENGTH)+removedType,
277
                                      removedName,
278
                                      mObjectID);
279
    }
280
  
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282
  
283
  protected long addBase(Effect effect)
284
    {
285
    int type = effect.getType();
286

    
287
    mName[mNumEffects] = effect.getName();
288
    mType[mNumEffects] = type;
289
    mCurrentDuration[mNumEffects] = 0;
290
    
291
    int index = mFreeIndexes[mNumEffects];
292
    long id = mTotalEffects*mMax[mMaxIndex] + index;
293
    mID[mNumEffects] = id;
294
    mIDIndex[index] = mNumEffects;  
295
   
296
    mNumEffects++; 
297
    mTotalEffects++;
298
   
299
    return (id<<Effect.LENGTH)+type;
300
    }
301
    
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303
// used only for debugging
304

    
305
  @SuppressWarnings("unused")
306
  protected String printEffects(int max)
307
    {
308
    long[] indexes = new long[mMax[mMaxIndex]];
309
   
310
    for(int g=0; g<mMax[mMaxIndex]; g++)
311
      {
312
      indexes[g] = -1;  
313
      }
314
   
315
    String ret="(";
316
    int f;
317
   
318
    for(int g=0; g<max; g++) 
319
      {
320
      f = getEffectIndex(g);
321
      if( f>=0 ) indexes[f] = g;
322
      }
323
   
324
    for(int g=0; g<mMax[mMaxIndex]; g++)
325
      {
326
      ret += (g>0 ? ",":"")+(indexes[g]>=0 ? indexes[g] : " ");   
327
      }
328
   
329
    ret += ")";
330
   
331
    return ret;
332
    }
333

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335
// Only used for debugging
336
  
337
  protected boolean printByID(long id)
338
    {
339
    int index = getEffectIndex(id);
340
   
341
    if( index>=0 ) 
342
      {
343
      boolean inter0 = mInter[0][index]==null;
344
      boolean inter1 = mInter[1][index]==null;
345
      boolean inter2 = mInter[2][index]==null;
346

    
347
      android.util.Log.e("EffectQueue", "numEffects="+mNumEffects+" effect id="+id+" index="+index+
348
                         " duration="+mCurrentDuration[index]+" inter[0] null="+inter0+" inter[1] null="+inter1+" inter[2] null="+inter2);
349

    
350
      if( !inter0 ) android.util.Log.e("EffectQueue","inter[0]: "+mInter[0][index].print());
351
      if( !inter1 ) android.util.Log.e("EffectQueue","inter[1]: "+mInter[1][index].print());
352
      if( !inter2 ) android.util.Log.e("EffectQueue","inter[2]: "+mInter[2][index].print());
353

    
354
      return true;
355
      }
356
   
357
    android.util.Log.e("EffectQueue", "effect id="+id+" not found");
358

    
359
    return false;  
360
    }
361
 
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
  abstract void moveEffect(int index);
365
  }
366
///////////////////////////////////////////////////////////////////////////////////////////////////
(17-17/24)