Project

General

Profile

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

library / src / main / java / org / distorted / library / EffectQueue.java @ 54fe333a

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;
21

    
22
import org.distorted.library.message.EffectListener;
23
import org.distorted.library.message.EffectMessage;
24
import org.distorted.library.type.Dynamic;
25

    
26
import java.util.Vector;
27

    
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

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

    
49
  private static boolean mCreated;
50

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

    
65
    int max = mMax[mMaxIndex];
66

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

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

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

    
90
  @SuppressWarnings("unused")
91
  int getNumEffects()
92
    {
93
    return mNumEffects;  
94
    }
95

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

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

    
108
      mMax[index] = m;
109
      return true;
110
      }
111

    
112
    return false;
113
    }
114

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

    
117
  static int getMax(int index)
118
    {
119
    return mMax[index];
120
    }
121

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

    
124
  void registerForMessages(EffectListener el)
125
    {
126
    if( mListeners==null ) mListeners = new Vector<>(2,2);
127

    
128
    if( !mListeners.contains(el) )
129
      {
130
      mListeners.add(el);
131
      mNumListeners++;
132
      }
133
    }
134
 
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  void deregisterForMessages(EffectListener el)
138
    {
139
    if( mListeners.remove(el) )
140
      {
141
      mNumListeners--;
142
      }
143
    }
144

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

    
147
  static void onDestroy()
148
    {
149
    EffectTypes.reset(mMax);
150
    mCreated = false;  
151
    }
152
 
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

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

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

    
170
  synchronized int removeByType(EffectNames effect)
171
    {
172
    int ret = 0;
173
    int ord = effect.ordinal();  
174
     
175
    for(int i=0; i<mNumEffects; i++)
176
      {
177
      if( mName[i]==ord )
178
        {
179
        remove(i);
180
        i--;
181
        ret++;
182
        }
183
      }
184
   
185
    return ret;
186
    }
187
  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
  
190
  private synchronized int getEffectIndex(long id)
191
    {
192
    int index = mIDIndex[(int)(id%mMax[mMaxIndex])];
193
    return (index<mNumEffects && mID[index]==id ? index : -1);
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197
// we do want to notify Listeners if they called 'abortAll' themselves but don't want to notify
198
// them if it is the library itself which is releasing resources.
199

    
200
  synchronized int abortAll(boolean notify)
201
    {
202
    int ret = mNumEffects;
203
    long removedID;
204
    int removedName;
205

    
206
    for(int i=0; i<ret; i++ )
207
      {
208
      mInter[0][i] = null;
209
      mInter[1][i] = null;
210
      mInter[2][i] = null;
211

    
212
      if( notify )
213
        {
214
        removedID = mID[i];
215
        removedName= mName[i];
216

    
217
        for(int j=0; j<mNumListeners; j++)
218
          EffectMessageSender.newMessage( mListeners.elementAt(j),
219
                                          EffectMessage.EFFECT_REMOVED,
220
                                          (removedID<<EffectTypes.LENGTH)+EffectNames.getType(removedName).type,
221
                                          removedName,
222
                                          mObjectID);
223
        }
224
      }
225

    
226
    mNumEffects= 0;
227

    
228
    return ret;
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232
// this assumes 0<=effect<mNumEffects
233
  
234
  protected void remove(int effect)
235
    {
236
    mNumEffects--;     
237
    
238
    byte removedIndex = (byte)(mID[effect]%mMax[mMaxIndex]);
239
    byte removedPosition = mIDIndex[removedIndex];
240
    mFreeIndexes[mNumEffects] = removedIndex;
241
    
242
    long removedID = mID[effect];
243
    int removedName= mName[effect];
244
    
245
    for(int j=0; j<mMax[mMaxIndex]; j++)
246
      {
247
      if( mIDIndex[j] > removedPosition ) mIDIndex[j]--; 
248
      }
249
         
250
    for(int j=effect; j<mNumEffects; j++ ) 
251
      {
252
      mName[j]            = mName[j+1];
253
      mInter[0][j]        = mInter[0][j+1];
254
      mInter[1][j]        = mInter[1][j+1];
255
      mInter[2][j]        = mInter[2][j+1];
256
      mCurrentDuration[j] = mCurrentDuration[j+1];
257
      mID[j]              = mID[j+1];
258
    
259
      moveEffect(j);
260
      }
261
   
262
    mInter[0][mNumEffects] = null;
263
    mInter[1][mNumEffects] = null;
264
    mInter[2][mNumEffects] = null;
265

    
266
    for(int i=0; i<mNumListeners; i++) 
267
      EffectMessageSender.newMessage( mListeners.elementAt(i),
268
                                      EffectMessage.EFFECT_REMOVED,
269
                                      (removedID<<EffectTypes.LENGTH)+EffectNames.getType(removedName).type,
270
                                      removedName,
271
                                      mObjectID);
272
    }
273
  
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
  
276
  protected long addBase(EffectNames name)
277
    {    
278
    mName[mNumEffects]  = name.ordinal();
279
    mCurrentDuration[mNumEffects] = 0;
280
    
281
    int index = mFreeIndexes[mNumEffects];
282
    long id = mTotalEffects*mMax[mMaxIndex] + index;
283
    mID[mNumEffects] = id;
284
    mIDIndex[index] = mNumEffects;  
285
   
286
    mNumEffects++; 
287
    mTotalEffects++;
288
   
289
    return (id<<EffectTypes.LENGTH)+name.getType().type;
290
    }
291
    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293
// used only for debugging
294

    
295
  @SuppressWarnings("unused")
296
  protected String printEffects(int max)
297
    {
298
    long[] indexes = new long[mMax[mMaxIndex]];
299
   
300
    for(int g=0; g<mMax[mMaxIndex]; g++)
301
      {
302
      indexes[g] = -1;  
303
      }
304
   
305
    String ret="(";
306
    int f;
307
   
308
    for(int g=0; g<max; g++) 
309
      {
310
      f = getEffectIndex(g);
311
      if( f>=0 ) indexes[f] = g;
312
      }
313
   
314
    for(int g=0; g<mMax[mMaxIndex]; g++)
315
      {
316
      ret += (g>0 ? ",":"")+(indexes[g]>=0 ? indexes[g] : " ");   
317
      }
318
   
319
    ret += ")";
320
   
321
    return ret;
322
    }
323

    
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325
// Only used for debugging
326
  
327
  protected boolean printByID(long id)
328
    {
329
    int index = getEffectIndex(id);
330
   
331
    if( index>=0 ) 
332
      {
333
      boolean inter0 = mInter[0][index]==null;
334
      boolean inter1 = mInter[1][index]==null;
335
      boolean inter2 = mInter[2][index]==null;
336

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

    
340
      if( !inter0 ) android.util.Log.e("EffectQueue","inter[0]: "+mInter[0][index].print());
341
      if( !inter1 ) android.util.Log.e("EffectQueue","inter[1]: "+mInter[1][index].print());
342
      if( !inter2 ) android.util.Log.e("EffectQueue","inter[2]: "+mInter[2][index].print());
343

    
344
      return true;
345
      }
346
   
347
    android.util.Log.e("EffectQueue", "effect id="+id+" not found");
348

    
349
    return false;  
350
    }
351
 
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  abstract void moveEffect(int index);
355
  }
356
///////////////////////////////////////////////////////////////////////////////////////////////////
(15-15/23)