Project

General

Profile

« Previous | Next » 

Revision 809dcae3

Added by Leszek Koltunski about 5 years ago

Finally move the EffectQueues to their own package.

View differences:

src/main/java/org/distorted/library/effectqueue/EffectQueue.java
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.effectqueue;
21

  
22
import org.distorted.library.effect.Effect;
23
import org.distorted.library.effect.EffectName;
24
import org.distorted.library.effect.EffectType;
25
import org.distorted.library.main.Distorted;
26
import org.distorted.library.main.DistortedMaster;
27
import org.distorted.library.message.EffectListener;
28
import org.distorted.library.message.EffectMessage;
29
import org.distorted.library.message.EffectMessageSender;
30

  
31
import java.util.ArrayList;
32
import java.util.HashMap;
33

  
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35
/**
36
 * Not part of public API, do not document
37
 *
38
 * @y.exclude
39
 */
40
public abstract class EffectQueue implements DistortedMaster.Slave
41
  {
42
  static final int MAIN_VARIANTS = 3; // Number of Main program variants (ATM 3: MAIN, MAIN OIT, PREPROCESS)
43

  
44
  private static final int CREATE = 0;
45
  private static final int ATTACH = 1;
46
  private static final int DETACH = 2;
47
  private static final int DETALL = 3;
48

  
49
  int mNumEffects;              // 'ToBe' will be more than mNumEffects if doWork() hasn't
50
  private int mNumEffectsToBe;  // added them yet (or less if it hasn't removed some yet)
51
  float[] mUniforms;
52
  long[] mCurrentDuration;
53
  Effect[] mEffects;
54
  int[] mName;
55
  long mTime=0;
56
  ArrayList<EffectListener> mListeners =null;
57
  int mNumListeners=0;  // ==mListeners.length(), but we only create mListeners if the first one gets added
58
  long mDistortedEffectsID;
59

  
60
  private static int[] mMax = new int[EffectType.LENGTH];
61
  private static long mNextID;
62
  private static HashMap<ArrayList<Long>,Long> mMapID = new HashMap<>(); // maps lists of Effect IDs (longs) to a
63
                                                                         // single long - the queue ID.
64
  private long mID;
65
  private int mIndex;
66
  private boolean mCreated;
67

  
68
  private class Job
69
    {
70
    int type;
71
    int num;
72
    boolean notify;
73
    Effect effect;
74

  
75
    Job(int t, int m, boolean n, Effect e)
76
      {
77
      type  = t;
78
      num   = m;
79
      notify= n;
80
      effect= e;
81
      }
82
    }
83

  
84
  private ArrayList<Job> mJobs = new ArrayList<>();
85

  
86
  static
87
    {
88
    onDestroy();
89
    }
90
  
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92
   
93
  EffectQueue(long id, int numUniforms, int index)
94
    {
95
    mCreated            = false;
96
    mID                 = 0;
97
    mNumEffects         = 0;
98
    mNumEffectsToBe     = 0;
99
    mDistortedEffectsID = id;
100
    mIndex              = index;
101

  
102
    mJobs.add(new Job(CREATE,numUniforms,false,null));  // create the stuff that depends on max number
103
    DistortedMaster.newSlave(this);                     // of uniforms later, on first render.
104
    }
105

  
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107

  
108
  public static void allocateQueues(EffectQueue[] queues, EffectQueue[] from, int flags, long id)
109
    {
110
    queues[0] = (flags & Distorted.CLONE_MATRIX     ) != 0 ? from[0] : new EffectQueueMatrix(id);
111
    queues[1] = (flags & Distorted.CLONE_VERTEX     ) != 0 ? from[1] : new EffectQueueVertex(id);
112
    queues[2] = (flags & Distorted.CLONE_FRAGMENT   ) != 0 ? from[2] : new EffectQueueFragment(id);
113
    queues[3] = (flags & Distorted.CLONE_POSTPROCESS) != 0 ? from[3] : new EffectQueuePostprocess(id);
114
    }
115

  
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

  
118
  public static void compute(EffectQueue[] queues, long currTime, float halfW, float halfH, float halfZ )
119
    {
120
    ((EffectQueueMatrix     )queues[0]).compute(currTime);
121
    ((EffectQueueVertex     )queues[1]).compute(currTime,halfW,halfH,halfZ);
122
    ((EffectQueueFragment   )queues[2]).compute(currTime,halfW,halfH,halfZ);
123
    ((EffectQueuePostprocess)queues[3]).compute(currTime);
124
    }
125

  
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127

  
128
  public static void send( EffectQueue[] queues, int width, int height, float distance, float mipmap,
129
                           float[] projection, float inflate, float halfW, float halfH, float halfZ, int variant )
130
    {
131
    ((EffectQueueMatrix  )queues[0]).send(width, height, distance, mipmap, projection, halfW, halfH, halfZ, variant);
132
    ((EffectQueueVertex  )queues[1]).send(inflate, variant);
133
    ((EffectQueueFragment)queues[2]).send(variant);
134
    }
135

  
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

  
138
  public static float[] getMVP(EffectQueue[] queues)
139
    {
140
    return ((EffectQueueMatrix)queues[0]).getMVP();
141
    }
142

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

  
145
  public static void getUniforms(int programH, int variant)
146
    {
147
    EffectQueueFragment.uniforms(programH,variant);
148
    EffectQueueVertex  .uniforms(programH,variant);
149
    EffectQueueMatrix  .uniforms(programH,variant);
150
    }
151

  
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153
// Every effect queue has an ID, which should be the same iff two queues hold the same effects.
154
// (this is a speedup: then both queues can be applied once, which seriously speeds up stuff -
155
// especially important in case of postprocessing)
156

  
157
  private void regenerateID()
158
    {
159
    if( mNumEffects>0 )
160
      {
161
      ArrayList<Long> list = new ArrayList<>();
162
      for (int i = 0; i < mNumEffects; i++) list.add(mEffects[i].getID());
163
      Long id = mMapID.get(list);
164

  
165
      if( id!=null )
166
        {
167
        mID = id;
168
        }
169
      else
170
        {
171
        mMapID.put(list,mNextID);
172
        mID = mNextID++;
173
        }
174
      }
175
    else
176
      {
177
      mID = 0;
178
      }
179
    }
180

  
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

  
183
  public long getID()
184
    {
185
    return mID;
186
    }
187

  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

  
190
  public static boolean setMax(int index, int m)
191
    {
192
    if( !Distorted.isInitialized() || m<=mMax[index] )
193
      {
194
      mMax[index] = m<0 ? 0:m;
195
      return true;
196
      }
197

  
198
    return false;
199
    }
200

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

  
203
  public static int getMax(int index)
204
    {
205
    return mMax[index];
206
    }
207

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

  
210
  public void registerForMessages(EffectListener el)
211
    {
212
    if( mListeners==null ) mListeners = new ArrayList<>();
213

  
214
    if( !mListeners.contains(el) )
215
      {
216
      mListeners.add(el);
217
      mNumListeners++;
218
      }
219
    }
220
 
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

  
223
  public void deregisterForMessages(EffectListener el)
224
    {
225
    if( mListeners.remove(el) )
226
      {
227
      mNumListeners--;
228
      }
229
    }
230

  
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

  
233
  public static void onDestroy()
234
    {
235
    mNextID = 1;
236
    mMapID.clear();
237
    EffectType.reset(mMax);
238
    }
239

  
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241
// this assumes 0<=effect<mNumEffects
242

  
243
  protected void remove(int effect)
244
    {
245
    mNumEffects--;
246

  
247
    long removedID = mEffects[effect].getID();
248

  
249
    for(int j=effect; j<mNumEffects; j++ )
250
      {
251
      mEffects[j]         = mEffects[j+1];
252
      mCurrentDuration[j] = mCurrentDuration[j+1];
253
      mName[j]            = mName[j+1];
254
      }
255

  
256
    mEffects[mNumEffects] = null;
257

  
258
    for(int i=0; i<mNumListeners; i++)
259
      EffectMessageSender.newMessage( mListeners.get(i), EffectMessage.EFFECT_REMOVED, removedID, mDistortedEffectsID);
260
    }
261

  
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

  
264
  public synchronized int removeByName(EffectName name)
265
    {
266
    int ret = 0;
267

  
268
    for(int i=0; i<mNumEffects; i++)
269
      {
270
      if( mEffects[i].getName() == name )
271
        {
272
        mJobs.add(new Job(DETACH,0,true,mEffects[i]));
273
        ret++;
274
        }
275
      }
276

  
277
    if( ret>0 )
278
      {
279
      DistortedMaster.newSlave(this);
280
      mNumEffectsToBe-=ret;
281
      }
282

  
283
    return ret;
284
    }
285

  
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

  
288
  public synchronized int removeById(long id)
289
    {
290
    for(int i=0; i<mNumEffects; i++)
291
      {
292
      if( mEffects[i].getID() == id )
293
        {
294
        mJobs.add(new Job(DETACH,0,true,mEffects[i]));
295
        DistortedMaster.newSlave(this);
296
        mNumEffectsToBe--;
297
        return 1;
298
        }
299
      }
300

  
301
    return 0;
302
    }
303

  
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

  
306
  public synchronized int removeEffect(Effect effect)
307
    {
308
    for(int i=0; i<mNumEffects; i++)
309
      {
310
      if( mEffects[i]==effect )
311
        {
312
        mJobs.add(new Job(DETACH,0,true,mEffects[i]));
313
        DistortedMaster.newSlave(this);
314
        mNumEffectsToBe--;
315
        return 1;
316
        }
317
      }
318
   
319
    return 0;
320
    }
321

  
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323
// we do want to notify Listeners if they called 'abortAll' themselves but don't want to notify
324
// them if it is the library itself which is releasing resources.
325

  
326
  public synchronized int abortAll(boolean notify)
327
    {
328
    mJobs.add(new Job(DETALL,0,notify,null));
329
    DistortedMaster.newSlave(this);
330
    mNumEffectsToBe = 0;
331
    return mNumEffects;
332
    }
333

  
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335
  
336
  public boolean add(Effect effect)
337
    {
338
    if( mMax[mIndex]>mNumEffectsToBe || !mCreated )
339
      {
340
      mJobs.add(new Job(ATTACH,0,false,effect));
341
      DistortedMaster.newSlave(this);
342
      mNumEffectsToBe++;
343
      return true;
344
      }
345

  
346
    return false;
347
    }
348

  
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

  
351
  public void doWork()
352
    {
353
    boolean changed = false;
354
    int num = mJobs.size();
355
    Job job;
356

  
357
    for(int i=0; i<num; i++)
358
      {
359
      job = mJobs.remove(0);
360

  
361
      switch(job.type)
362
        {
363
        case CREATE: int max = mMax[mIndex];
364
                     if( max>0 )
365
                       {
366
                       mUniforms        = new float[max*job.num];
367
                       mCurrentDuration = new long[max];
368
                       mEffects         = new Effect[max];
369
                       mName            = new int[max];
370
                       }
371
                     mCreated = true;
372

  
373
                     break;
374
        case ATTACH: if( mMax[mIndex]>mNumEffects ) // it is possible that we have first
375
                       {                            // added effects and then lowered mMax
376
                       mCurrentDuration[mNumEffects] = 0;
377
                       mEffects[mNumEffects] = job.effect;
378
                       mName[mNumEffects] = job.effect.getName().ordinal();
379
                       mNumEffects++;
380
                       changed = true;
381
                       }
382
                     else
383
                       {
384
                       android.util.Log.e("queue", "failed to add effect "+job.effect.getName());
385
                       }
386
                     break;
387
        case DETACH: for(int j=0; j<mNumEffects; j++)
388
                       {
389
                       if (mEffects[j] == job.effect)
390
                         {
391
                         remove(j);
392
                         changed = true;
393
                         break;
394
                         }
395
                       }
396
                     break;
397
        case DETALL: for(int j=0; j<mNumEffects; j++ )
398
                       {
399
                       changed = true;
400

  
401
                       if( job.notify )
402
                         {
403
                         for(int k=0; k<mNumListeners; k++)
404
                           EffectMessageSender.newMessage( mListeners.get(k), EffectMessage.EFFECT_REMOVED, mEffects[j].getID(), mDistortedEffectsID);
405
                         }
406

  
407
                       mEffects[j] = null;
408
                       }
409

  
410
                     mNumEffects= 0;
411
                     break;
412
        }
413
      }
414

  
415
    if( changed && mIndex==EffectType.POSTPROCESS.ordinal() ) regenerateID();
416
    }
417
  }
src/main/java/org/distorted/library/effectqueue/EffectQueueFragment.java
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.effectqueue;
21

  
22
import android.opengl.GLES31;
23

  
24
import org.distorted.library.effect.EffectType;
25
import org.distorted.library.effect.FragmentEffect;
26
import org.distorted.library.message.EffectMessage;
27
import org.distorted.library.message.EffectMessageSender;
28

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

  
31
class EffectQueueFragment extends EffectQueue
32
  {
33
  private static final int NUM_UNIFORMS = FragmentEffect.NUM_UNIFORMS;
34
  private static final int INDEX = EffectType.FRAGMENT.ordinal();
35

  
36
  private static int[] mNumEffectsH = new int[MAIN_VARIANTS];
37
  private static int[] mNameH       = new int[MAIN_VARIANTS];
38
  private static int[] mUniformsH   = new int[MAIN_VARIANTS];
39

  
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41
   
42
  EffectQueueFragment(long id)
43
    { 
44
    super(id,NUM_UNIFORMS,INDEX);
45
    }
46

  
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

  
49
  static void uniforms(int mProgramH, int variant)
50
    {
51
    mNumEffectsH[variant]= GLES31.glGetUniformLocation( mProgramH, "fNumEffects");
52
    mNameH[variant]      = GLES31.glGetUniformLocation( mProgramH, "fName");
53
    mUniformsH[variant]  = GLES31.glGetUniformLocation( mProgramH, "fUniforms");
54
    }
55

  
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57
  
58
  void compute(long currTime,float halfX, float halfY, float halfZ)
59
    { 
60
    if( currTime==mTime ) return;
61
    if( mTime==0 ) mTime = currTime;
62
    long step = (currTime-mTime);
63

  
64
    for(int i=0; i<mNumEffects; i++)
65
      {
66
      mCurrentDuration[i] += step;
67

  
68
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
69
        {
70
        for(int j=0; j<mNumListeners; j++)
71
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
72
        }
73

  
74
      mUniforms[NUM_UNIFORMS*i+5] -= halfX;
75
      mUniforms[NUM_UNIFORMS*i+6] -= halfY;
76
      mUniforms[NUM_UNIFORMS*i+7] -= halfZ;
77
      }
78

  
79
    mTime = currTime;  
80
    }
81

  
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83
  
84
  void send(int variant)
85
    {
86
    GLES31.glUniform1i( mNumEffectsH[variant], mNumEffects);
87

  
88
    if( mNumEffects>0 )
89
      {
90
      GLES31.glUniform1iv( mNameH[variant]    ,                 mNumEffects, mName    ,0);
91
      GLES31.glUniform4fv( mUniformsH[variant],(NUM_UNIFORMS/4)*mNumEffects, mUniforms,0);
92
      }  
93
    }
94
  }
src/main/java/org/distorted/library/effectqueue/EffectQueueMatrix.java
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.effectqueue;
21

  
22
import android.opengl.GLES31;
23
import android.opengl.Matrix;
24

  
25
import org.distorted.library.effect.EffectType;
26
import org.distorted.library.effect.MatrixEffect;
27
import org.distorted.library.message.EffectMessage;
28
import org.distorted.library.message.EffectMessageSender;
29

  
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

  
32
class EffectQueueMatrix extends EffectQueue
33
  {   
34
  private static final int NUM_UNIFORMS = MatrixEffect.NUM_UNIFORMS;
35
  private static final int INDEX = EffectType.MATRIX.ordinal();
36

  
37
  private static float[] mMVPMatrix = new float[16];
38
  private static float[] mViewMatrix= new float[16];
39

  
40
  private static int[] mObjDH      = new int[MAIN_VARIANTS];
41
  private static int[] mMVPMatrixH = new int[MAIN_VARIANTS];
42
  private static int[] mMVMatrixH  = new int[MAIN_VARIANTS];
43

  
44
  private static float[] mTmpMatrix = new float[16];
45
  private static float[] mTmpResult = new float[4];
46
  private static float[] mTmpPoint  = new float[4];
47
  private static float mMinX,mMaxX,mMinY,mMaxY;
48

  
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50
   
51
  EffectQueueMatrix(long id)
52
    { 
53
    super(id,NUM_UNIFORMS,INDEX );
54
    }
55

  
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

  
58
  static void uniforms(int mProgramH, int variant)
59
    {
60
    mObjDH[variant]     = GLES31.glGetUniformLocation(mProgramH, "u_objD");
61
    mMVPMatrixH[variant]= GLES31.glGetUniformLocation(mProgramH, "u_MVPMatrix");
62
    mMVMatrixH[variant] = GLES31.glGetUniformLocation(mProgramH, "u_MVMatrix");
63
    }
64

  
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

  
67
  private void magnifyDir()
68
    {
69
    Matrix.multiplyMV(mTmpResult,0,mTmpMatrix,0,mTmpPoint,0);
70
    float nx = mTmpResult[0]/mTmpResult[3];
71
    float ny = mTmpResult[1]/mTmpResult[3];
72

  
73
    if( nx<mMinX ) mMinX = nx;
74
    if( nx>mMaxX ) mMaxX = nx;
75
    if( ny<mMinY ) mMinY = ny;
76
    if( ny>mMaxY ) mMaxY = ny;
77
    }
78

  
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80
// return a float which describes how much larger an object must be so that it appears to be (about)
81
// 'marginInPixels' pixels larger in each direction. Used in Postprocessing.
82

  
83
  float magnify(float[] projection, int width, int height, float mipmap, float halfX, float halfY, float halfZ, float marginInPixels)
84
    {
85
    mMinX = Integer.MAX_VALUE;
86
    mMaxX = Integer.MIN_VALUE;
87
    mMinY = Integer.MAX_VALUE;
88
    mMaxY = Integer.MIN_VALUE;
89

  
90
    mTmpPoint[3] = 1.0f;
91

  
92
    Matrix.multiplyMM(mTmpMatrix, 0, projection, 0, mViewMatrix, 0);
93

  
94
    mTmpPoint[0] = +halfX; mTmpPoint[1] = +halfY; mTmpPoint[2] = +halfZ; magnifyDir();
95
    mTmpPoint[0] = +halfX; mTmpPoint[1] = +halfY; mTmpPoint[2] = -halfZ; magnifyDir();
96
    mTmpPoint[0] = +halfX; mTmpPoint[1] = -halfY; mTmpPoint[2] = +halfZ; magnifyDir();
97
    mTmpPoint[0] = +halfX; mTmpPoint[1] = -halfY; mTmpPoint[2] = -halfZ; magnifyDir();
98
    mTmpPoint[0] = -halfX; mTmpPoint[1] = +halfY; mTmpPoint[2] = +halfZ; magnifyDir();
99
    mTmpPoint[0] = -halfX; mTmpPoint[1] = +halfY; mTmpPoint[2] = -halfZ; magnifyDir();
100
    mTmpPoint[0] = -halfX; mTmpPoint[1] = -halfY; mTmpPoint[2] = +halfZ; magnifyDir();
101
    mTmpPoint[0] = -halfX; mTmpPoint[1] = -halfY; mTmpPoint[2] = -halfZ; magnifyDir();
102

  
103
    float xLenInPixels = width *(mMaxX-mMinX)/2;
104
    float yLenInPixels = height*(mMaxY-mMinY)/2;
105

  
106
    // already margin / avg(xLen,yLen) is the size of the halo.
107
    // Here we need a bit more because we are marking not only the halo, but a little bit around
108
    // it as well so that the (blur for example) will be smooth on the edges. Thus the 2.0f.
109
    // ( 4.0 because there is an extra 2.0 from the avg(xLen,yLen) )
110
    //
111
    // mMipmap ( 1.0, 0.5, 0.25, 0.125 ) - we need to make the size of the halo independent
112
    // of postprocessing effect quality.
113

  
114
    return mipmap*4.0f*marginInPixels/( xLenInPixels+yLenInPixels );
115
    }
116

  
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

  
119
  void compute(long currTime)
120
    {
121
    if( currTime==mTime ) return;
122
    if( mTime==0 ) mTime = currTime;
123
    long step = (currTime-mTime);
124

  
125
    for(int i=0; i<mNumEffects; i++)
126
      {
127
      mCurrentDuration[i] += step;
128

  
129
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
130
        {
131
        for(int j=0; j<mNumListeners; j++)
132
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
133
        }
134
      }
135
     
136
    mTime = currTime;  
137
    }  
138

  
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

  
141
  float[] getMVP()
142
    {
143
    return mMVPMatrix;
144
    }
145

  
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

  
148
  void send(int width, int height, float distance, float mipmap, float[] projection, float halfX, float halfY, float halfZ, int variant)
149
    {
150
    Matrix.setIdentityM(mViewMatrix, 0);
151
    Matrix.translateM(mViewMatrix, 0, -width*0.5f, -height*0.5f, -distance);
152
    if( mipmap!=1 ) Matrix.scaleM(mViewMatrix, 0, mipmap, mipmap, mipmap);
153

  
154
    for(int i=0; i<mNumEffects; i++) ((MatrixEffect)mEffects[i]).apply(mViewMatrix,mUniforms,i);
155

  
156
    Matrix.translateM(mViewMatrix, 0, halfX,halfY,halfZ);
157
    Matrix.multiplyMM(mMVPMatrix, 0, projection, 0, mViewMatrix, 0);
158

  
159
    GLES31.glUniform3f( mObjDH[variant] , halfX, halfY, halfZ);
160
    GLES31.glUniformMatrix4fv(mMVMatrixH[variant] , 1, false, mViewMatrix, 0);
161
    GLES31.glUniformMatrix4fv(mMVPMatrixH[variant], 1, false, mMVPMatrix , 0);
162
    }
163
  }
src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.java
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.effectqueue;
21

  
22
import android.content.res.Resources;
23
import android.opengl.GLES31;
24
import android.util.Log;
25

  
26
import org.distorted.library.R;
27
import org.distorted.library.effect.EffectType;
28
import org.distorted.library.effect.PostprocessEffect;
29
import org.distorted.library.effect.VertexEffect;
30
import org.distorted.library.main.Distorted;
31
import org.distorted.library.main.DistortedFramebuffer;
32
import org.distorted.library.main.DistortedNode;
33
import org.distorted.library.main.DistortedOutputSurface;
34
import org.distorted.library.main.DistortedRenderState;
35
import org.distorted.library.main.DistortedSurface;
36
import org.distorted.library.mesh.MeshBase;
37
import org.distorted.library.message.EffectMessage;
38
import org.distorted.library.message.EffectMessageSender;
39
import org.distorted.library.program.DistortedProgram;
40

  
41
import java.io.InputStream;
42

  
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44
/**
45
 * Not part of public API, do not document
46
 *
47
 * @y.exclude
48
 */
49
public class EffectQueuePostprocess extends EffectQueue
50
  {
51
  private static final int NUM_UNIFORMS = PostprocessEffect.NUM_UNIFORMS;
52
  private static final int INDEX = EffectType.POSTPROCESS.ordinal();
53

  
54
  private int mHalo;
55
  private float mR, mG, mB, mA;
56

  
57
  private static DistortedProgram mPreProgram;
58
  private static int mPreColorH;
59
  private static int mPreTextureH;
60

  
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

  
63
  EffectQueuePostprocess(long id)
64
    { 
65
    super(id,NUM_UNIFORMS,INDEX );
66
    }
67

  
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69

  
70
  void compute(long currTime)
71
    {
72
    if( currTime==mTime ) return;
73
    if( mTime==0 ) mTime = currTime;
74
    long step = (currTime-mTime);
75

  
76
    mR = mG = mB = mA = 0.0f;
77
    mHalo = 0;
78
    int halo;
79

  
80
    for(int i=0; i<mNumEffects; i++)
81
      {
82
      mCurrentDuration[i] += step;
83

  
84
      // first zero out the 'alpha' because BLUR effect will not overwrite this (it is a 1D effect)
85
      // and if previously there was a GLOW effect here then mA would be non-zero and we don't want
86
      // that (see preprocess())
87
      mUniforms[NUM_UNIFORMS*i+4]=0.0f;
88

  
89
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
90
        {
91
        for(int j=0; j<mNumListeners; j++)
92
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
93
        }
94

  
95
      halo = (int)mUniforms[NUM_UNIFORMS*i];
96
      if( halo>mHalo ) mHalo = halo;
97
      }
98

  
99
    // TODO  (now only really works in case of 1 effect!)
100
    if( mNumEffects>0 )
101
      {
102
      mR = mUniforms[1];
103
      mG = mUniforms[2];
104
      mB = mUniforms[3];
105
      mA = mUniforms[4];
106
      }
107

  
108
    mTime = currTime;
109
    }
110

  
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112

  
113
  public static void createPrograms(Resources resources)
114
    {
115
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
116
    final InputStream mainFragStream = resources.openRawResource(R.raw.preprocess_fragment_shader);
117

  
118
    int numV = VertexEffect.getNumEnabled();
119

  
120
    String mainVertHeader= Distorted.GLSL_VERSION + ("#define NUM_VERTEX "   + ( numV>0 ? Distorted.getMax(EffectType.VERTEX  ) : 0 ) + "\n");
121
    String mainFragHeader= Distorted.GLSL_VERSION + "\n";
122

  
123
    String enabledEffectV= VertexEffect.getGLSL();
124

  
125
    try
126
      {
127
      mPreProgram = new DistortedProgram(mainVertStream, mainFragStream, mainVertHeader, mainFragHeader,
128
                                         enabledEffectV, null, Distorted.GLSL, null);
129
      }
130
    catch(Exception e)
131
      {
132
      Log.e("POSTPROCESS", e.getClass().getSimpleName()+" trying to compile PRE program: "+e.getMessage());
133
      throw new RuntimeException(e.getMessage());
134
      }
135

  
136
    int preProgramH = mPreProgram.getProgramHandle();
137
    EffectQueueVertex.getUniforms( preProgramH,2 );
138
    EffectQueueMatrix.getUniforms( preProgramH,2 );
139
    mPreColorH  = GLES31.glGetUniformLocation( preProgramH, "u_Color"  );
140
    mPreTextureH= GLES31.glGetUniformLocation( preProgramH, "u_Texture");
141
    }
142

  
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144
// TODO  (now only really works in case of 1 effect!)
145

  
146
  public int getQuality()
147
    {
148
    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getQuality() : 0;
149
    }
150

  
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152
// TODO  (now only really works in case of 1 effect!)
153

  
154
  public boolean getRender()
155
    {
156
    return mNumEffects>0 ? ((PostprocessEffect)mEffects[0]).getRender() : false;
157
    }
158

  
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

  
161
  public int preprocess(DistortedOutputSurface buffer, DistortedNode node, float distance, float mipmap, float[] projection)
162
    {
163
    buffer.setAsOutput();
164
    DistortedSurface input = node.getInternalSurface();
165

  
166
    if( input.setAsInput() )
167
      {
168
      MeshBase mesh = node.getMesh();
169

  
170
      float halfW = input.getWidth() / 2.0f;
171
      float halfH = input.getHeight()/ 2.0f;
172
      float halfZ = halfW*mesh.getZFactor();
173

  
174
      int width = buffer.getWidth();
175
      int height = buffer.getHeight();
176

  
177
      DistortedRenderState.setUpStencilMark(mA!=0.0f);
178
      DistortedRenderState.disableBlending();
179

  
180
      GLES31.glViewport(0, 0, width, height );
181

  
182
      mPreProgram.useProgram();
183

  
184
      mesh.bindVertexAttribs(mPreProgram);
185

  
186
      EffectQueue[] queues = node.getEffects().getQueues();
187
      EffectQueueMatrix matrix = (EffectQueueMatrix)queues[0];
188
      EffectQueueVertex vertex = (EffectQueueVertex)queues[1];
189

  
190
      float inflate=0.0f;
191

  
192
      matrix.send(width, height, distance, mipmap, projection, halfW, halfH, halfZ, 2);
193

  
194
      if( mHalo!=0.0f )
195
        {
196
        inflate = matrix.magnify(projection, width, height, mipmap, halfW, halfH, halfZ, mHalo);
197
        }
198

  
199
      vertex.send(inflate,2);
200

  
201
      if( mA!=0.0f )
202
        {
203
        GLES31.glUniform4f(mPreColorH, mR, mG, mB, mA);
204
        GLES31.glUniform1i(mPreTextureH, 0);
205
        }
206

  
207
      GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.getNumVertices() );
208

  
209
      DistortedRenderState.restoreBlending();
210
      DistortedRenderState.unsetUpStencilMark();
211

  
212
      return 1;
213
      }
214
    return 0;
215
    }
216

  
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

  
219
  public int postprocess(DistortedFramebuffer buffer)
220
    {
221
    int numRenders = 0;
222

  
223
    GLES31.glDisable(GLES31.GL_BLEND);
224

  
225
    for(int i=0; i<mNumEffects; i++)
226
      {
227
      numRenders += ((PostprocessEffect)mEffects[i]).apply(mUniforms,NUM_UNIFORMS*i, buffer);
228
      }
229

  
230
    GLES31.glEnable(GLES31.GL_BLEND);
231

  
232
    return numRenders;
233
    }
234
  }
src/main/java/org/distorted/library/effectqueue/EffectQueueVertex.java
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.effectqueue;
21

  
22
import android.opengl.GLES31;
23

  
24
import org.distorted.library.effect.EffectType;
25
import org.distorted.library.effect.VertexEffect;
26
import org.distorted.library.message.EffectMessage;
27
import org.distorted.library.message.EffectMessageSender;
28

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

  
31
class EffectQueueVertex extends EffectQueue
32
  { 
33
  private static final int NUM_UNIFORMS = VertexEffect.NUM_UNIFORMS;
34
  private static final int INDEX = EffectType.VERTEX.ordinal();
35

  
36
  private static int[] mNumEffectsH = new int[MAIN_VARIANTS];
37
  private static int[] mNameH       = new int[MAIN_VARIANTS];
38
  private static int[] mUniformsH   = new int[MAIN_VARIANTS];
39
  private static int[] mInflateH    = new int[MAIN_VARIANTS];
40

  
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42
   
43
  EffectQueueVertex(long id)
44
    { 
45
    super(id,NUM_UNIFORMS,INDEX);
46
    }
47

  
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

  
50
  static void uniforms(int mProgramH, int variant)
51
    {
52
    mNumEffectsH[variant]= GLES31.glGetUniformLocation( mProgramH, "vNumEffects");
53
    mNameH[variant]      = GLES31.glGetUniformLocation( mProgramH, "vName");
54
    mUniformsH[variant]  = GLES31.glGetUniformLocation( mProgramH, "vUniforms");
55
    mInflateH[variant]   = GLES31.glGetUniformLocation( mProgramH, "u_Inflate");
56
    }
57

  
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59
  
60
  void compute(long currTime,float halfX, float halfY, float halfZ)
61
    {
62
    if( currTime==mTime ) return;
63
    if( mTime==0 ) mTime = currTime;
64
    long step = (currTime-mTime);
65

  
66
    for(int i=0; i<mNumEffects; i++)
67
      {
68
      mCurrentDuration[i] += step;
69

  
70
      if( mEffects[i].compute(mUniforms, NUM_UNIFORMS*i, mCurrentDuration[i], step) )
71
        {
72
        for(int j=0; j<mNumListeners; j++)
73
          EffectMessageSender.newMessage( mListeners.get(j), EffectMessage.EFFECT_FINISHED, mEffects[i].getID(), mDistortedEffectsID);
74
        }
75

  
76
      mUniforms[NUM_UNIFORMS*i+5] -= halfX;
77
      mUniforms[NUM_UNIFORMS*i+6] -= halfY;
78
      mUniforms[NUM_UNIFORMS*i+7] -= halfZ;
79
      }
80

  
81
    mTime = currTime;
82
    }
83

  
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

  
86
  void send(float inflate, int variant)
87
    {
88
    GLES31.glUniform1i( mNumEffectsH[variant], mNumEffects);
89
    GLES31.glUniform1f( mInflateH[variant]   , inflate    );
90

  
91
    if( mNumEffects>0 )
92
      {
93
      GLES31.glUniform1iv( mNameH[variant]    ,                 mNumEffects, mName    ,0);
94
      GLES31.glUniform4fv( mUniformsH[variant],(NUM_UNIFORMS/4)*mNumEffects, mUniforms,0);
95
      }
96
    }
97
  }
src/main/java/org/distorted/library/main/Distorted.java
28 28

  
29 29
import org.distorted.library.R;
30 30
import org.distorted.library.effect.Effect;
31
import org.distorted.library.effectqueue.EffectQueue;
32
import org.distorted.library.effectqueue.EffectQueuePostprocess;
31 33
import org.distorted.library.effect.EffectType;
32 34
import org.distorted.library.effect.FragmentEffect;
33 35
import org.distorted.library.effect.PostprocessEffect;
......
100 102
   * https://community.arm.com/graphics/f/discussions/10285/opengl-es-3-1-on-mali-t880-flashes
101 103
   */
102 104
  static final int FBO_QUEUE_SIZE = 4;
103
  /**
104
   * Number of Main program variants (ATM 3: MAIN, MAIN OIT, PREPROCESS)
105
   */
106
  static final int MAIN_VARIANTS = 3;
107 105

  
108 106
  private static boolean mInitialized=false;
109 107

  
......
200 198

  
201 199
///////////////////////////////////////////////////////////////////////////////////////////////////
202 200

  
203
  static void createPrograms(Resources resources)
201
  private static void createPrograms(Resources resources)
204 202
    {
205 203
    // MAIN PROGRAM ////////////////////////////////////
206 204
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
......
289 287

  
290 288
///////////////////////////////////////////////////////////////////////////////////////////////////
291 289

  
292
  static void createProgramsOIT(Resources resources)
290
  private static void createProgramsOIT(Resources resources)
293 291
    {
294 292
    // MAIN OIT PROGRAM ////////////////////////////////
295 293
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
......
406 404
    mOITRenderSizeH         = GLES31.glGetUniformLocation( oitRenderProgramH, "u_Size");
407 405
    }
408 406

  
409

  
410 407
///////////////////////////////////////////////////////////////////////////////////////////////////
411 408

  
412 409
  private static void displayNormals(EffectQueue[] queues, MeshBase mesh)
......
445 442

  
446 443
    mesh.bindVertexAttribs(Distorted.mMainOITProgram);
447 444

  
448
    float inflate = mesh.getInflate();
445
    float inflate     = mesh.getInflate();
446
    int width         = surface.mWidth;
447
    int height        = surface.mHeight;
448
    float distance    = surface.mDistance;
449
    float mipmap      = surface.mMipmap;
450
    float[] projection= surface.mProjectionMatrix;
449 451

  
450
    EffectQueue.send(queues, surface, inflate, halfW, halfH, halfZ, 1 );
452
    EffectQueue.send(queues, width, height, distance, mipmap, projection, inflate, halfW, halfH, halfZ, 1 );
451 453
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.getNumVertices() );
452 454

  
453 455
    if( mesh.getShowNormals() )
454 456
      {
455 457
      Distorted.mMainProgram.useProgram();
456
      EffectQueue.send(queues, surface, inflate, halfW, halfH, halfZ, 0 );
458
      EffectQueue.send(queues, width, height, distance, mipmap, projection, inflate, halfW, halfH, halfZ, 0 );
457 459
      displayNormals(queues,mesh);
458 460
      }
459 461
    }
......
469 471
    Distorted.mMainProgram.useProgram();
470 472
    GLES31.glUniform1i(Distorted.mMainTextureH, 0);
471 473
    mesh.bindVertexAttribs(Distorted.mMainProgram);
472
    EffectQueue.send(queues, surface, mesh.getInflate(), halfW, halfH, halfZ, 0 );
474

  
475
    float inflate     = mesh.getInflate();
476
    int width         = surface.mWidth;
477
    int height        = surface.mHeight;
478
    float distance    = surface.mDistance;
479
    float mipmap      = surface.mMipmap;
480
    float[] projection= surface.mProjectionMatrix;
481

  
482
    EffectQueue.send(queues, width, height, distance, mipmap, projection, inflate, halfW, halfH, halfZ, 0 );
473 483
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.getNumVertices() );
474 484

  
475 485
    if( mesh.getShowNormals() ) displayNormals(queues,mesh);
......
581 591
    }
582 592

  
583 593
///////////////////////////////////////////////////////////////////////////////////////////////////
584
// Pass1 of the OIT algorithm. Clear per-pixel head-poiners.
594
// Pass1 of the OIT algorithm. Clear per-pixel head-pointers.
585 595

  
586 596
  static void oitClear(DistortedOutputSurface surface, int counter)
587 597
    {
src/main/java/org/distorted/library/main/DistortedEffects.java
21 21

  
22 22
import org.distorted.library.effect.Effect;
23 23
import org.distorted.library.effect.EffectName;
24
import org.distorted.library.effectqueue.EffectQueue;
24 25
import org.distorted.library.effect.EffectType;
25 26
import org.distorted.library.message.EffectListener;
26 27

  
......
37 38
  private EffectQueue[] mQueues;
38 39

  
39 40
///////////////////////////////////////////////////////////////////////////////////////////////////
40

  
41
  EffectQueue[] getQueues()
41
/**
42
 * @y.exclude
43
 */
44
  public EffectQueue[] getQueues()
42 45
    {
43 46
    return mQueues;
44 47
    }
......
98 101
 * 
99 102
 * @param el A class implementing the EffectListener interface that wants to get notifications.
100 103
 */
101
  @SuppressWarnings("unused")
102 104
  public void registerForMessages(EffectListener el)
103 105
    {
104 106
    for( int i=0; i<EffectType.LENGTH; i++)
......
113 115
 * 
114 116
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
115 117
 */
116
  @SuppressWarnings("unused")
117 118
  public void deregisterForMessages(EffectListener el)
118 119
    {
119 120
    for( int i=0; i<EffectType.LENGTH; i++)
src/main/java/org/distorted/library/main/DistortedOutputSurface.java
23 23
import android.opengl.Matrix;
24 24

  
25 25
import org.distorted.library.effect.EffectQuality;
26
import org.distorted.library.effectqueue.EffectQueuePostprocess;
26 27
import org.distorted.library.mesh.MeshBase;
27 28

  
28 29
///////////////////////////////////////////////////////////////////////////////////////////////////
......
377 378

  
378 379
  int renderChildren(long time, int numChildren, DistortedChildrenList children, int fbo, boolean oit)
379 380
    {
380
    int quality=0, numRenders=0, bucketChange=0;
381
    int numRenders=0, bucketChange=0;
381 382
    DistortedNode child;
383
    DistortedFramebuffer buffer=null;
382 384
    EffectQueuePostprocess lastQueue=null, currQueue;
383 385
    long lastBucket=0, currBucket;
384 386
    boolean renderDirectly=false;
......
431 433
            }
432 434
          else
433 435
            {
434
            for(int j=bucketChange; j<i; j++) numRenders += lastQueue.preprocess( mBuffer[quality],children.getChild(j) );
435
            numRenders += lastQueue.postprocess(mBuffer[quality]);
436
            for(int j=bucketChange; j<i; j++) numRenders += lastQueue.preprocess( buffer,children.getChild(j), buffer.mDistance, buffer.mMipmap, buffer.mProjectionMatrix );
437
            numRenders += lastQueue.postprocess(buffer);
436 438

  
437 439
            if( oit )
438 440
              {
439
              numRenders += oitBuild(time, mBuffer[quality], fbo);
441
              numRenders += oitBuild(time, buffer, fbo);
440 442
              GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
441 443
              }
442 444
            else
443 445
              {
444
              numRenders += blitWithDepth(time, mBuffer[quality],fbo);
446
              numRenders += blitWithDepth(time, buffer, fbo);
445 447
              }
446
            mBuffer[quality].clearBuffer(fbo);
448
            buffer.clearBuffer(fbo);
447 449
            }
448 450

  
449
          quality= currQueue.getQuality();
451
          buffer= mBuffer[currQueue.getQuality()];
450 452
          bucketChange= i;
451 453
          renderDirectly = currQueue.getRender();
452 454
          }
......
467 469
          }
468 470
        else
469 471
          {
470
          mBuffer[quality].setAsOutput(time);
471
          child.drawNoBlend(time, mBuffer[quality]);
472
          buffer.setAsOutput(time);
473
          child.drawNoBlend(time, buffer);
472 474
          }
473 475

  
474 476
        if( i==numChildren-1 )
475 477
          {
476
          for(int j=bucketChange; j<numChildren; j++) numRenders += currQueue.preprocess( mBuffer[quality],children.getChild(j) );
477
          numRenders += currQueue.postprocess(mBuffer[quality]);
478
          for(int j=bucketChange; j<numChildren; j++) numRenders += currQueue.preprocess( buffer,children.getChild(j), buffer.mDistance, buffer.mMipmap, buffer.mProjectionMatrix );
479
          numRenders += currQueue.postprocess(buffer);
478 480

  
479 481
          if( oit )
480 482
            {
481
            numRenders += oitBuild(time, mBuffer[quality], fbo);
483
            numRenders += oitBuild(time, buffer, fbo);
482 484
            GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT | GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
483
            mBuffer[quality].clearBuffer(fbo);
485
            buffer.clearBuffer(fbo);
484 486
            }
485 487
          else
486 488
            {
487
            numRenders += blitWithDepth(time, mBuffer[quality],fbo);
489
            numRenders += blitWithDepth(time, buffer,fbo);
488 490
            }
489 491
          }
490 492
        } // end else (postprocessed child)
......
550 552
    DistortedRenderState.colorDepthStencilRestore();
551 553
    }
552 554

  
555
///////////////////////////////////////////////////////////////////////////////////////////////////
556

  
557
  void setAsOutput(long time)
558
    {
559
    GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[mCurrFBO]);
560

  
561
    if( mTime[mCurrFBO]!=time )
562
      {
563
      mTime[mCurrFBO] = time;
564
      clear();
565
      }
566
    }
567

  
553 568
///////////////////////////////////////////////////////////////////////////////////////////////////
554 569
// PUBLIC API
555 570
///////////////////////////////////////////////////////////////////////////////////////////////////
......
600 615
    return numRenders;
601 616
    }
602 617

  
603
///////////////////////////////////////////////////////////////////////////////////////////////////
604
/**
605
 * Bind this Surface as a Framebuffer we can render to.
606
 *
607
 * @param time Present time, in milliseconds. The point: looking at this param the library can figure
608
 *             out if this is the first time during present frame that this FBO is being set as output.
609
 *             If so, the library, in addition to binding the Surface for output, also clears the
610
 *             Surface's color and depth attachments.
611
 */
612
  public void setAsOutput(long time)
613
    {
614
    GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[mCurrFBO]);
615

  
616
    if( mTime[mCurrFBO]!=time )
617
      {
618
      mTime[mCurrFBO] = time;
619
      clear();
620
      }
621
    }
622

  
623 618
///////////////////////////////////////////////////////////////////////////////////////////////////
624 619
/**
625 620
 * Bind this Surface as a Framebuffer we can render to.
src/main/java/org/distorted/library/main/DistortedRenderState.java
186 186

  
187 187
///////////////////////////////////////////////////////////////////////////////////////////////////
188 188

  
189
  static void disableBlending()
189
  public static void disableBlending()
190 190
    {
191 191
    sState.blend = cState.blend;
192 192

  
......
199 199

  
200 200
///////////////////////////////////////////////////////////////////////////////////////////////////
201 201

  
202
  static void restoreBlending()
202
  public static void restoreBlending()
203 203
    {
204 204
    if (sState.blend != cState.blend)
205 205
      {
......
427 427

  
428 428
///////////////////////////////////////////////////////////////////////////////////////////////////
429 429

  
430
  static void setUpStencilMark(boolean color)
430
  public static void setUpStencilMark(boolean color)
431 431
    {
432 432
    sState.stencilTest = cState.stencilTest;
433 433

  
......
502 502

  
503 503
///////////////////////////////////////////////////////////////////////////////////////////////////
504 504

  
505
  static void unsetUpStencilMark()
505
  public static void unsetUpStencilMark()
506 506
    {
507 507
    if( sState.stencilTest!=cState.stencilTest )
508 508
      {
src/main/java/org/distorted/library/main/EffectQueue.java
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.effect.EffectName;
24
import org.distorted.library.effect.EffectType;
25
import org.distorted.library.message.EffectListener;
26
import org.distorted.library.message.EffectMessage;
27
import org.distorted.library.message.EffectMessageSender;
28

  
29
import java.util.ArrayList;
30
import java.util.HashMap;
31

  
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33

  
34
abstract class EffectQueue implements DistortedMaster.Slave
35
  {
36
  private static final int CREATE = 0;
37
  private static final int ATTACH = 1;
38
  private static final int DETACH = 2;
39
  private static final int DETALL = 3;
40

  
41
  int mNumEffects;              // 'ToBe' will be more than mNumEffects if doWork() hasn't
42
  private int mNumEffectsToBe;  // added them yet (or less if it hasn't removed some yet)
43
  float[] mUniforms;
44
  long[] mCurrentDuration;
45
  Effect[] mEffects;
46
  int[] mName;
47
  long mTime=0;
48
  ArrayList<EffectListener> mListeners =null;
49
  int mNumListeners=0;  // ==mListeners.length(), but we only create mListeners if the first one gets added
50
  long mDistortedEffectsID;
51

  
52
  private static int[] mMax = new int[EffectType.LENGTH];
53
  private static long mNextID;
54
  private static HashMap<ArrayList<Long>,Long> mMapID = new HashMap<>(); // maps lists of Effect IDs (longs) to a
55
                                                                         // single long - the queue ID.
56
  private long mID;
57
  private int mIndex;
58
  private boolean mCreated;
59

  
60
  private class Job
61
    {
62
    int type;
63
    int num;
64
    boolean notify;
65
    Effect effect;
66

  
67
    Job(int t, int m, boolean n, Effect e)
68
      {
69
      type  = t;
70
      num   = m;
71
      notify= n;
72
      effect= e;
73
      }
74
    }
75

  
76
  private ArrayList<Job> mJobs = new ArrayList<>();
77

  
78
  static
79
    {
80
    onDestroy();
81
    }
82
  
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84
   
85
  EffectQueue(long id, int numUniforms, int index)
86
    {
87
    mCreated            = false;
88
    mID                 = 0;
89
    mNumEffects         = 0;
90
    mNumEffectsToBe     = 0;
91
    mDistortedEffectsID = id;
92
    mIndex              = index;
93

  
94
    mJobs.add(new Job(CREATE,numUniforms,false,null));  // create the stuff that depends on max number
95
    DistortedMaster.newSlave(this);                     // of uniforms later, on first render.
96
    }
97

  
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

  
100
  static void allocateQueues(EffectQueue[] queues, EffectQueue[] from, int flags, long id)
101
    {
102
    queues[0] = (flags & Distorted.CLONE_MATRIX     ) != 0 ? from[0] : new EffectQueueMatrix(id);
103
    queues[1] = (flags & Distorted.CLONE_VERTEX     ) != 0 ? from[1] : new EffectQueueVertex(id);
104
    queues[2] = (flags & Distorted.CLONE_FRAGMENT   ) != 0 ? from[2] : new EffectQueueFragment(id);
105
    queues[3] = (flags & Distorted.CLONE_POSTPROCESS) != 0 ? from[3] : new EffectQueuePostprocess(id);
106
    }
107

  
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

  
110
  static void compute(EffectQueue[] queues, long currTime, float halfW, float halfH, float halfZ )
111
    {
112
    ((EffectQueueMatrix     )queues[0]).compute(currTime);
113
    ((EffectQueueVertex     )queues[1]).compute(currTime,halfW,halfH,halfZ);
114
    ((EffectQueueFragment   )queues[2]).compute(currTime,halfW,halfH,halfZ);
115
    ((EffectQueuePostprocess)queues[3]).compute(currTime);
116
    }
117

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

  
120
  static void send(EffectQueue[] queues, DistortedOutputSurface surface, float inflate, float halfW, float halfH, float halfZ, int variant )
121
    {
122
    ((EffectQueueMatrix  )queues[0]).send(surface,halfW,halfH,halfZ, variant);
123
    ((EffectQueueVertex  )queues[1]).send(inflate, variant);
124
    ((EffectQueueFragment)queues[2]).send(variant);
125
    }
126

  
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128

  
129
  static float[] getMVP(EffectQueue[] queues)
130
    {
131
    return ((EffectQueueMatrix)queues[0]).getMVP();
132
    }
133

  
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

  
136
  static void getUniforms(int programH, int variant)
137
    {
138
    EffectQueueFragment.getUniforms(programH,variant);
139
    EffectQueueVertex  .getUniforms(programH,variant);
140
    EffectQueueMatrix  .getUniforms(programH,variant);
141
    }
142

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff