Project

General

Profile

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

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

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
    if( mMax[mMaxIndex]>0 )
66
      {
67
      mName            = new int[mMax[mMaxIndex]];
68
      mUniforms        = new float[numUniforms*mMax[mMaxIndex]];
69
      mInter           = new Dynamic[3][mMax[mMaxIndex]];
70
      mCurrentDuration = new long[mMax[mMaxIndex]];
71
      mID              = new long[mMax[mMaxIndex]];
72
      mIDIndex         = new byte[mMax[mMaxIndex]];
73
      mFreeIndexes     = new byte[mMax[mMaxIndex]];
74
     
75
      for(byte i=0; i<mMax[mMaxIndex]; i++) mFreeIndexes[i] = i;
76

    
77
      if( numCache>0 )
78
        {
79
        mCache = new float[numCache*mMax[mMaxIndex]];
80
        }
81
      }
82
   
83
    mCreated = true;  
84
    }
85

    
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

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

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

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

    
106
      mMax[index] = m;
107
      return true;
108
      }
109

    
110
    return false;
111
    }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

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

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

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

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

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

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

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

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

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

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

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

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

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

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

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

    
224
    mNumEffects= 0;
225

    
226
    return ret;
227
    }
228

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

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

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

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

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

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

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

    
347
    return false;  
348
    }
349
 
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  abstract void moveEffect(int index);
353
  }
354
///////////////////////////////////////////////////////////////////////////////////////////////////
(8-8/15)