Project

General

Profile

« Previous | Next » 

Revision 11845a9e

Added by Leszek Koltunski about 5 years ago

Carve the 'children list' from DOutputSurface and DNode into a separate class of its own, DistortedChildrenList.

View differences:

src/main/java/org/distorted/library/main/DistortedChildrenList.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 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

  
21
package org.distorted.library.main;
22

  
23
import org.distorted.library.mesh.MeshBase;
24

  
25
import java.util.ArrayList;
26

  
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

  
29
class DistortedChildrenList implements DistortedMaster.Slave
30
  {
31
  private static final int ATTACH = 0;
32
  private static final int DETACH = 1;
33
  private static final int DETALL = 2;
34
  private static final int SORT   = 3;
35

  
36
  private class Job
37
    {
38
    int type;
39
    DistortedNode node;
40

  
41
    Job(int t, DistortedNode n)
42
      {
43
      type = t;
44
      node = n;
45
      }
46
    }
47

  
48
  private ArrayList<Job> mJobs;
49
  private ArrayList<DistortedNode> mChildren;
50
  private DistortedChildrenList.Parent mParent;
51
  private int mNumChildren;
52

  
53
  public interface Parent
54
    {
55
    void adjustIsomorphism();
56
    DistortedChildrenList getChildren();
57
    }
58

  
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

  
61
  DistortedChildrenList(DistortedChildrenList.Parent parent)
62
    {
63
    mParent = parent;
64
    mJobs = new ArrayList<>();
65
    mChildren = null;
66
    mNumChildren = 0;
67
    }
68

  
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

  
71
  int getNumChildren()
72
    {
73
    return mNumChildren;
74
    }
75

  
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

  
78
  DistortedNode getChild(int index)
79
    {
80
    return mChildren.get(index);
81
    }
82

  
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

  
85
  void removeChild(DistortedNode node)
86
    {
87
    if( mChildren.remove(node) )
88
      {
89
      mNumChildren--;
90
      }
91
    }
92

  
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94
// Can make this logarithmic but the typical number of children is very small anyway.
95
//
96
// We want to keep same buckets next to each other, while avoiding changes in order of the children
97
// (if possible!) We want to keep bucket=0 (i.e. the non-postprocessed children) at the beginning.
98

  
99
  void addSortingByBuckets(DistortedNode newChild)
100
    {
101
    int i;
102
    long bucket = newChild.getPostprocessQueue().getID();
103
    boolean sameBucket = false;
104

  
105
    for(i=0; i<mNumChildren; i++)
106
      {
107
      if( mChildren.get(i).getPostprocessQueue().getID() == bucket )
108
        {
109
        sameBucket=true;
110
        }
111
      else if( sameBucket || bucket==0 )
112
        {
113
        break;
114
        }
115
      }
116

  
117
    mChildren.add(i,newChild);
118
    mNumChildren++;
119
    }
120

  
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

  
123
  void attach(DistortedNode node)
124
    {
125
    mJobs.add(new Job(ATTACH,node));
126
    DistortedMaster.newSlave(this);
127
    }
128

  
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

  
131
  DistortedNode attach(DistortedSurface surface, DistortedEffects effects, MeshBase mesh)
132
    {
133
    DistortedNode node = new DistortedNode(surface,effects,mesh);
134
    mJobs.add(new Job(ATTACH,node));
135
    DistortedMaster.newSlave(this);
136
    return node;
137
    }
138

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

  
141
  void detach(DistortedNode node)
142
    {
143
    mJobs.add(new Job(DETACH,node));
144
    DistortedMaster.newSlave(this);
145
    }
146

  
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

  
149
  void detach(DistortedEffects effects)
150
    {
151
    long id = effects.getID();
152
    DistortedNode node;
153
    boolean detached = false;
154

  
155
    for(int i=0; i<mNumChildren; i++)
156
      {
157
      node = mChildren.get(i);
158

  
159
      if( node.getEffects().getID()==id )
160
        {
161
        detached = true;
162
        mJobs.add(new Job(DETACH,node));
163
        DistortedMaster.newSlave(this);
164
        break;
165
        }
166
      }
167

  
168
    if( !detached )
169
      {
170
      // if we failed to detach any, it still might be the case that
171
      // there's an ATTACH job that we need to cancel.
172
      int num = mJobs.size();
173
      Job job;
174

  
175
      for(int i=0; i<num; i++)
176
        {
177
        job = mJobs.get(i);
178

  
179
        if( job.type==ATTACH && job.node.getEffects()==effects )
180
          {
181
          mJobs.remove(i);
182
          break;
183
          }
184
        }
185
      }
186
    }
187

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

  
190
  void detachAll()
191
    {
192
    mJobs.add(new Job(DETALL,null));
193
    DistortedMaster.newSlave(this);
194
    }
195

  
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197
/**
198
 * This is not really part of the public API. Has to be public only because it is a part of the
199
 * DistortedSlave interface, which should really be a class that we extend here instead but
200
 * Java has no multiple inheritance.
201
 *
202
 * @y.exclude
203
 */
204
  public void doWork()
205
    {
206
    int num = mJobs.size();
207

  
208
    if( num>0 )
209
      {
210
      Job job;
211
      int numChanges=0;
212

  
213
      for(int i=0; i<num; i++)
214
        {
215
        job = mJobs.remove(0);
216

  
217
        switch(job.type)
218
          {
219
          case ATTACH: numChanges++;
220
                       if( mChildren==null ) mChildren = new ArrayList<>(2);
221
                       job.node.setParent(mParent);
222
                       addSortingByBuckets(job.node);
223
                       break;
224
          case DETACH: numChanges++;
225
                       if( mNumChildren>0 && mChildren.remove(job.node) )
226
                         {
227
                         job.node.setParent(null);
228
                         mNumChildren--;
229
                         }
230
                       break;
231
          case DETALL: numChanges++;
232
                       if( mNumChildren>0 )
233
                         {
234
                         DistortedNode tmp;
235

  
236
                         for(int j=mNumChildren-1; j>=0; j--)
237
                           {
238
                           tmp = mChildren.remove(j);
239
                           tmp.setParent(null);
240
                           }
241

  
242
                         mNumChildren = 0;
243
                         }
244
                       break;
245
          case SORT  : mChildren.remove(job.node);
246
                       addSortingByBuckets(job.node);
247
                       break;
248
          }
249
        }
250
      if( numChanges>0 ) mParent.adjustIsomorphism();
251
      }
252
    }
253
  }
254

  
src/main/java/org/distorted/library/main/DistortedMaster.java
99 99
    if( !found ) mSlaves.add(s);
100 100
    }
101 101

  
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103
// Can make this logarithmic but the typical number of children is very small anyway.
104
//
105
// We want to keep same buckets next to each other, while avoiding changes in order of the children
106
// (if possible!) We want to keep bucket=0 (i.e. the non-postprocessed children) at the beginning.
107

  
108
  static void addSortingByBuckets(ArrayList<DistortedNode> mChildren, DistortedNode newChild)
109
    {
110
    int i,num = mChildren.size();
111
    long bucket = newChild.getPostprocessQueue().getID();
112
    boolean sameBucket = false;
113

  
114
    for(i=0; i<num; i++)
115
      {
116
      if( mChildren.get(i).getPostprocessQueue().getID() == bucket )
117
        {
118
        sameBucket=true;
119
        }
120
      else if( sameBucket || bucket==0 )
121
        {
122
        break;
123
        }
124
      }
125

  
126
    mChildren.add(i,newChild);
127

  
128
    //android.util.Log.e("newChild", "newBucket="+bucket+" new child at "+i+" total num ="+num);
129
    }
130

  
131 102
///////////////////////////////////////////////////////////////////////////////////////////////////
132 103

  
133 104
  static void onDestroy()
src/main/java/org/distorted/library/main/DistortedNode.java
37 37
 * to sub-class 'NodeData'. Two identical sub-trees attached at different points of the main tree
38 38
 * will point to the same NodeData; only the first of this is rendered (mData.numRender!).
39 39
 */
40
public class DistortedNode implements DistortedMaster.Slave
40
public class DistortedNode implements DistortedChildrenList.Parent
41 41
  {
42
  private static final int ATTACH = 0;
43
  private static final int DETACH = 1;
44
  private static final int DETALL = 2;
45
  private static final int SORT   = 3;
46

  
47
  private class Job
48
    {
49
    int type;
50
    DistortedNode node;
51

  
52
    Job(int t, DistortedNode n)
53
      {
54
      type = t;
55
      node = n;
56
      }
57
    }
58

  
59
  private ArrayList<Job> mJobs = new ArrayList<>();
60

  
61
  private ArrayList<DistortedNode> mChildren;
62
  private int[] mNumChildren;  // ==mChildren.length(), but we only create mChildren if the first one gets added
63

  
64
  private boolean mRenderWayOIT;
65
  private DistortedNode mParent;
66
  private DistortedOutputSurface mSurfaceParent;
67 42
  private MeshBase mMesh;
68 43
  private DistortedEffects mEffects;
69 44
  private DistortedSurface mSurface;
70 45
  private DistortedRenderState mState;
71 46
  private DistortedNodeData mData;
47
  private DistortedChildrenList mChildren;
48
  private DistortedChildrenList.Parent mParent;
49

  
72 50
  private int mFboW, mFboH, mFboDepthStencil;
51
  private boolean mRenderWayOIT;
73 52

  
74 53
///////////////////////////////////////////////////////////////////////////////////////////////////
75 54

  
......
89 68
  private ArrayList<Long> generateIDList()
90 69
    {
91 70
    ArrayList<Long> ret = new ArrayList<>();
71
    int numChildren = mChildren.getNumChildren();
92 72

  
93
    if( mNumChildren[0]==0 )
73
    if( numChildren==0 )
94 74
      {
95 75
      // add a negative number so this leaf never gets confused with a internal node
96 76
      // with a single child that happens to have ID identical to some leaf's Effects ID.
......
100 80
      {
101 81
      DistortedNode node;
102 82
   
103
      for(int i=0; i<mNumChildren[0]; i++)
83
      for(int i=0; i<numChildren; i++)
104 84
        {
105
        node = mChildren.get(i);
85
        node = mChildren.getChild(i);
106 86
        ret.add(node.mData.ID);
107 87
        }
108 88

  
......
129 109
    }
130 110

  
131 111
///////////////////////////////////////////////////////////////////////////////////////////////////
132
// tree isomorphism algorithm
133

  
134
  private void adjustIsomorphism()
112
/**
113
 * This is not really part of the public API. Has to be public only because it is a part of the
114
 * DistortedChildrenList.Parent interface.
115
 *
116
 * @y.exclude
117
 */
118
  public void adjustIsomorphism()
135 119
    {
136 120
    DistortedNodeData newData = DistortedNodeData.returnData(generateIDList());
137 121
    boolean deleteOldFBO = mData.removeData();
138
    boolean createNewFBO = (mNumChildren[0]>0 && newData.mFBO==null);
122
    boolean createNewFBO = (mChildren.getNumChildren()>0 && newData.mFBO==null);
139 123

  
140 124
    if( deleteOldFBO && createNewFBO )
141 125
      {
......
148 132
      }
149 133
    else if( createNewFBO )
150 134
      {
151
      int width  = mFboW <= 0 ? mSurface.getWidth()  : mFboW;
152
      int height = mFboH <= 0 ? mSurface.getHeight() : mFboH;
153
      newData.mFBO = new DistortedFramebuffer(1,mFboDepthStencil, DistortedSurface.TYPE_TREE, width, height);
135
      newData.mFBO = allocateNewFBO();
154 136
      }
155 137

  
156 138
    mData = newData;
......
158 140
    if( mParent!=null ) mParent.adjustIsomorphism();
159 141
    }
160 142

  
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144
/**
145
 * This is not really part of the public API. Has to be public only because it is a part of the
146
 * DistortedChildrenList.Parent interface.
147
 *
148
 * @y.exclude
149
 */
150
  public DistortedChildrenList getChildren()
151
    {
152
    return mChildren;
153
    }
154

  
161 155
///////////////////////////////////////////////////////////////////////////////////////////////////
162 156
// return the total number of render calls issued
163 157

  
164 158
  int drawNoBlend(long currTime, DistortedOutputSurface surface)
165 159
    {
166
    DistortedSurface input = mNumChildren[0]==0 ? mSurface : mData.mFBO;
160
    DistortedSurface input = getInternalSurface();
167 161

  
168 162
    if( input.setAsInput() )
169 163
      {
......
182 176

  
183 177
  int drawOIT(long currTime, DistortedOutputSurface surface)
184 178
    {
185
    DistortedSurface input = mNumChildren[0]==0 ? mSurface : mData.mFBO;
179
    DistortedSurface input = getInternalSurface();
186 180

  
187 181
    if( input.setAsInput() )
188 182
      {
......
199 193

  
200 194
  int draw(long currTime, DistortedOutputSurface surface)
201 195
    {
202
    DistortedSurface input = mNumChildren[0]==0 ? mSurface : mData.mFBO;
196
    DistortedSurface input = getInternalSurface();
203 197

  
204 198
    if( input.setAsInput() )
205 199
      {
......
217 211
  int renderRecursive(long currTime)
218 212
    {
219 213
    int numRenders = 0;
214
    int numChildren = mChildren.getNumChildren();
220 215

  
221
    if( mNumChildren[0]>0 && mData.notRenderedYetAtThisTime(currTime) )
216
    if( numChildren>0 && mData.notRenderedYetAtThisTime(currTime) )
222 217
      {
223
      for (int i=0; i<mNumChildren[0]; i++)
224
        {
225
        numRenders += mChildren.get(i).renderRecursive(currTime);
226
        }
227

  
228
      if( mData.mFBO==null )
218
      for (int i=0; i<numChildren; i++)
229 219
        {
230
        int width  = mFboW <= 0 ? mSurface.getWidth()  : mFboW;
231
        int height = mFboH <= 0 ? mSurface.getHeight() : mFboH;
232
        mData.mFBO = new DistortedFramebuffer(1,mFboDepthStencil, DistortedSurface.TYPE_TREE, width, height);
220
        numRenders += mChildren.getChild(i).renderRecursive(currTime);
233 221
        }
234 222

  
223
      if( mData.mFBO==null ) mData.mFBO = allocateNewFBO();
235 224
      mData.mFBO.setAsOutput(currTime);
236 225

  
237 226
      if( mSurface.setAsInput() )
......
240 229
        DistortedEffects.blitPriv(mData.mFBO);
241 230
        }
242 231

  
243
      numRenders += mData.mFBO.renderChildren(currTime,mNumChildren[0],mChildren,0, mRenderWayOIT);
232
      numRenders += mData.mFBO.renderChildren(currTime,numChildren,mChildren,0, mRenderWayOIT);
244 233
      }
245 234

  
246 235
    return numRenders;
......
248 237

  
249 238
///////////////////////////////////////////////////////////////////////////////////////////////////
250 239

  
251
  void setSurfaceParent(DistortedOutputSurface dep)
240
  private DistortedFramebuffer allocateNewFBO()
252 241
    {
253
    mSurfaceParent = dep;
254
    mParent = null;
242
    int width  = mFboW <= 0 ? mSurface.getWidth()  : mFboW;
243
    int height = mFboH <= 0 ? mSurface.getHeight() : mFboH;
244
    return new DistortedFramebuffer(1,mFboDepthStencil, DistortedSurface.TYPE_TREE, width, height);
245
    }
246

  
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

  
249
  void setParent(DistortedChildrenList.Parent parent)
250
    {
251
    mParent = parent;
255 252
    }
256 253

  
257 254
///////////////////////////////////////////////////////////////////////////////////////////////////
......
260 257
    {
261 258
    if( mParent!=null )
262 259
      {
263
      mParent.mChildren.remove(this);
264
      DistortedMaster.addSortingByBuckets(mParent.mChildren,this);
265
      }
266
    else if( mSurfaceParent!=null )
267
      {
268
      ArrayList<DistortedNode> children = mSurfaceParent.getChildren();
269
      children.remove(this);
270
      DistortedMaster.addSortingByBuckets(children,this);
260
      DistortedChildrenList siblings = mParent.getChildren();
261
      siblings.removeChild(this);
262
      siblings.addSortingByBuckets(this);
271 263
      }
272 264
    }
273 265

  
......
294 286
    mEffects       = effects;
295 287
    mMesh          = mesh;
296 288
    mState         = new DistortedRenderState();
297
    mChildren      = null;
298
    mNumChildren   = new int[1];
289
    mChildren      = new DistortedChildrenList(this);
299 290
    mParent        = null;
300
    mSurfaceParent = null;
301 291
    mRenderWayOIT  = false;
302 292

  
303 293
    mFboW            = 0;  // i.e. take this from
......
324 314
    mMesh         = node.mMesh;
325 315
    mState        = new DistortedRenderState();
326 316
    mParent       = null;
327
    mSurfaceParent= null;
328 317
    mRenderWayOIT = false;
329 318

  
330 319
    mFboW            = node.mFboW;
......
357 346
        mSurface = new DistortedFramebuffer(1,depthStencil,DistortedSurface.TYPE_TREE,w,h);
358 347
        }
359 348
      }
349

  
360 350
    if( (flags & Distorted.CLONE_CHILDREN) != 0 )
361 351
      {
362
      if( node.mChildren==null )     // do NOT copy over the NULL!
363
        {
364
        node.mChildren = new ArrayList<>(2);
365
        }
366

  
367 352
      mChildren = node.mChildren;
368
      mNumChildren = node.mNumChildren;
369 353
      }
370 354
    else
371 355
      {
372
      mChildren = null;
373
      mNumChildren = new int[1];
356
      mChildren = new DistortedChildrenList(this);
374 357
      }
375 358

  
376 359
    mData = DistortedNodeData.returnData(generateIDList());
......
427 410
 */
428 411
  public void attach(DistortedNode node)
429 412
    {
430
    mJobs.add(new Job(ATTACH,node));
431
    DistortedMaster.newSlave(this);
413
    mChildren.attach(node);
432 414
    }
433 415

  
434 416
///////////////////////////////////////////////////////////////////////////////////////////////////
......
445 427
 */
446 428
  public DistortedNode attach(DistortedSurface surface, DistortedEffects effects, MeshBase mesh)
447 429
    {
448
    DistortedNode node = new DistortedNode(surface,effects,mesh);
449
    mJobs.add(new Job(ATTACH,node));
450
    DistortedMaster.newSlave(this);
451
    return node;
430
    return mChildren.attach(surface,effects,mesh);
452 431
    }
453 432

  
454 433
///////////////////////////////////////////////////////////////////////////////////////////////////
......
462 441
 */
463 442
  public void detach(DistortedNode node)
464 443
    {
465
    mJobs.add(new Job(DETACH,node));
466
    DistortedMaster.newSlave(this);
444
    mChildren.detach(node);
467 445
    }
468 446

  
469 447
///////////////////////////////////////////////////////////////////////////////////////////////////
......
480 458
 */
481 459
  public void detach(DistortedEffects effects)
482 460
    {
483
    long id = effects.getID();
484
    DistortedNode node;
485
    boolean detached = false;
486

  
487
    for(int i=0; i<mNumChildren[0]; i++)
488
      {
489
      node = mChildren.get(i);
490

  
491
      if( node.getEffects().getID()==id )
492
        {
493
        detached = true;
494
        mJobs.add(new Job(DETACH,node));
495
        DistortedMaster.newSlave(this);
496
        break;
497
        }
498
      }
499

  
500
    if( !detached )
501
      {
502
      // if we failed to detach any, it still might be the case that
503
      // there's an ATTACH job that we need to cancel.
504
      int num = mJobs.size();
505
      Job job;
506

  
507
      for(int i=0; i<num; i++)
508
        {
509
        job = mJobs.get(i);
510

  
511
        if( job.type==ATTACH && job.node.getEffects()==effects )
512
          {
513
          mJobs.remove(i);
514
          break;
515
          }
516
        }
517
      }
461
    mChildren.detach(effects);
518 462
    }
519 463

  
520 464
///////////////////////////////////////////////////////////////////////////////////////////////////
......
526 470
 */
527 471
  public void detachAll()
528 472
    {
529
    mJobs.add(new Job(DETALL,null));
530
    DistortedMaster.newSlave(this);
531
    }
532

  
533
///////////////////////////////////////////////////////////////////////////////////////////////////
534
/**
535
 * This is not really part of the public API. Has to be public only because it is a part of the
536
 * DistortedSlave interface, which should really be a class that we extend here instead but
537
 * Java has no multiple inheritance.
538
 *
539
 * @y.exclude
540
 */
541
  public void doWork()
542
    {
543
    int num = mJobs.size();
544

  
545
    if( num>0 )
546
      {
547
      Job job;
548
      int numChanges=0;
549

  
550
      for(int i=0; i<num; i++)
551
        {
552
        job = mJobs.remove(0);
553

  
554
        switch(job.type)
555
          {
556
          case ATTACH: numChanges++;
557
                       if( mChildren==null ) mChildren = new ArrayList<>(2);
558
                       job.node.mParent = this;
559
                       job.node.mSurfaceParent = null;
560
                       DistortedMaster.addSortingByBuckets(mChildren,job.node);
561
                       mNumChildren[0]++;
562
                       break;
563
          case DETACH: numChanges++;
564
                       if( mNumChildren[0]>0 && mChildren.remove(job.node) )
565
                         {
566
                         job.node.mParent = null;
567
                         job.node.mSurfaceParent = null;
568
                         mNumChildren[0]--;
569
                         }
570
                       break;
571
          case DETALL: numChanges++;
572
                       if( mNumChildren[0]>0 )
573
                         {
574
                         DistortedNode tmp;
575

  
576
                         for(int j=mNumChildren[0]-1; j>=0; j--)
577
                           {
578
                           tmp = mChildren.remove(j);
579
                           tmp.mParent = null;
580
                           tmp.mSurfaceParent = null;
581
                           }
582

  
583
                         mNumChildren[0] = 0;
584
                         }
585
                       break;
586
          case SORT  : mChildren.remove(job.node);
587
                       DistortedMaster.addSortingByBuckets(mChildren,job.node);
588
                       break;
589
          }
590
        }
591
      if( numChanges>0 ) adjustIsomorphism();
592
      }
473
    mChildren.detachAll();
593 474
    }
594 475

  
595 476
///////////////////////////////////////////////////////////////////////////////////////////////////
......
622 503
   */
623 504
  public DistortedSurface getInternalSurface()
624 505
    {
625
    return mNumChildren[0]==0 ? mSurface : mData.mFBO;
506
    return mChildren.getNumChildren()==0 ? mSurface : mData.mFBO;
626 507
    }
627 508

  
628 509
///////////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/main/DistortedOutputSurface.java
25 25
import org.distorted.library.effect.EffectQuality;
26 26
import org.distorted.library.mesh.MeshBase;
27 27

  
28
import java.util.ArrayList;
29

  
30 28
///////////////////////////////////////////////////////////////////////////////////////////////////
31 29
/**
32 30
 * This is not really part of the public API.
33 31
 *
34 32
 * @y.exclude
35 33
 */
36
public abstract class DistortedOutputSurface extends DistortedSurface implements DistortedMaster.Slave
34
public abstract class DistortedOutputSurface extends DistortedSurface implements DistortedChildrenList.Parent
37 35
{
38
/**
39
 * Do not create DEPTH or STENCIL attachment
40
 */
41 36
  public static final int NO_DEPTH_NO_STENCIL = 0;
42
/**
43
 * Create DEPTH, but not STENCIL
44
 */
45 37
  public static final int DEPTH_NO_STENCIL    = 1;
46
/**
47
 * Create both DEPTH and STENCIL
48
 */
49 38
  public static final int BOTH_DEPTH_STENCIL  = 2;
50 39

  
51
  private static final int ATTACH = 0;
52
  private static final int DETACH = 1;
53
  private static final int DETALL = 2;
54
  private static final int SORT   = 3;
55

  
56
  private ArrayList<DistortedNode> mChildren;
57
  private int mNumChildren;   // ==mChildren.length(), but we only create mChildren if the first one gets added
58
  private boolean mRenderWayOIT;
59

  
60
  private class Job
61
    {
62
    int type;
63
    DistortedNode node;
64

  
65
    Job(int t, DistortedNode n)
66
      {
67
      type = t;
68
      node = n;
69
      }
70
    }
71

  
72
  private ArrayList<Job> mJobs = new ArrayList<>();
73

  
74
  // Global buffers used for postprocessing.
75
  private static DistortedFramebuffer[] mBuffer=null;
76

  
77
  float mFOV;
78
  float mDistance, mNear;
40
  float mFOV, mDistance, mNear;
79 41
  float[] mProjectionMatrix;
80 42

  
81 43
  int mDepthStencilCreated;
82 44
  int mDepthStencil;
83 45
  int[] mDepthStencilH;
84 46
  int[] mFBOH;
85
  private long[] mTime;
86 47

  
87
  private float mClearR, mClearG, mClearB, mClearA;
88
  private float mClearDepth;
89
  private int mClearStencil;
90
  private int mClear;
91 48
  float mMipmap;
92 49

  
93 50
  int mRealWidth;   // the Surface can be backed up with a texture that is
......
97 54

  
98 55
  int mCurrFBO;     // internal current FBO (see Distorted.FBO_QUEUE_SIZE)
99 56

  
57
  private static DistortedFramebuffer[] mBuffer=null; // Global buffers used for postprocessing.
58
  private long[] mTime;
59
  private float mClearR, mClearG, mClearB, mClearA, mClearDepth;
60
  private int mClear, mClearStencil;
61
  private boolean mRenderWayOIT;
62
  private DistortedChildrenList mChildren;
63

  
100 64
///////////////////////////////////////////////////////////////////////////////////////////////////
101 65

  
102 66
  DistortedOutputSurface(int width, int height, int createColor, int numfbos, int numcolors, int depthStencil, int fbo, int type)
......
137 101

  
138 102
    mMipmap = 1.0f;
139 103

  
104
    mChildren = new DistortedChildrenList(this);
105

  
140 106
    createProjection();
141 107
    }
142 108

  
......
409 375
// to a whole buffer (lastQueue.postprocess) and merge it (this.oitBuild or blitWithDepth - depending
410 376
// on the type of rendering)
411 377

  
412
  int renderChildren(long time, int numChildren, ArrayList<DistortedNode> children, int fbo, boolean oit)
378
  int renderChildren(long time, int numChildren, DistortedChildrenList children, int fbo, boolean oit)
413 379
    {
414 380
    int quality=0, numRenders=0, bucketChange=0;
415 381
    DistortedNode child;
......
431 397

  
432 398
    for(int i=0; i<numChildren; i++)
433 399
      {
434
      child = children.get(i);
400
      child = children.getChild(i);
435 401
      currQueue = child.getPostprocessQueue();
436 402
      currBucket= currQueue.getID();
437 403

  
......
465 431
            }
466 432
          else
467 433
            {
468
            for(int j=bucketChange; j<i; j++) numRenders += lastQueue.preprocess( mBuffer[quality],children.get(j) );
434
            for(int j=bucketChange; j<i; j++) numRenders += lastQueue.preprocess( mBuffer[quality],children.getChild(j) );
469 435
            numRenders += lastQueue.postprocess(mBuffer[quality]);
470 436

  
471 437
            if( oit )
......
507 473

  
508 474
        if( i==numChildren-1 )
509 475
          {
510
          for(int j=bucketChange; j<numChildren; j++) numRenders += currQueue.preprocess( mBuffer[quality],children.get(j) );
476
          for(int j=bucketChange; j<numChildren; j++) numRenders += currQueue.preprocess( mBuffer[quality],children.getChild(j) );
511 477
          numRenders += currQueue.postprocess(mBuffer[quality]);
512 478

  
513 479
          if( oit )
......
536 502
    }
537 503

  
538 504
///////////////////////////////////////////////////////////////////////////////////////////////////
539

  
540
  ArrayList<DistortedNode> getChildren()
505
/**
506
 * This is not really part of the public API. Has to be public only because it is a part of the
507
 * DistortedChildrenList.Parent interface.
508
 *
509
 * @y.exclude
510
 */
511
  public DistortedChildrenList getChildren()
541 512
    {
542 513
    return mChildren;
543 514
    }
544 515

  
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517
/**
518
 * This is not really part of the public API. Has to be public only because it is a part of the
519
 * DistortedChildrenList.Parent interface.
520
 *
521
 * @y.exclude
522
 */
523
  public void adjustIsomorphism()
524
    {
525

  
526
    }
527

  
545 528
///////////////////////////////////////////////////////////////////////////////////////////////////
546 529
/**
547 530
 * Not part of the Public API.
......
611 594
 */
612 595
  public int render(long time, int fbo)
613 596
    {
614
    // change tree topology (attach and detach children)
615
/*
616
    boolean changed1 =
617
*/
618 597
    DistortedMaster.toDo();
619
/*
620
    if( changed1 )
621
      {
622
      for(int i=0; i<mNumChildren; i++)
623
        {
624
        mChildren.get(i).debug(0);
625
        }
626

  
627
      DistortedNode.debugMap();
628
      }
629
*/
630
    // create and delete all underlying OpenGL resources
631
    // Watch out: FIRST change topology, only then deal
632
    // with OpenGL resources. That's because changing Tree
633
    // can result in additional Framebuffers that would need
634
    // to be created immediately, before the calls to drawRecursive()
635
/*
636
    boolean changed2 =
637
*/
638 598
    toDo();
639
/*
640
    if( changed2 )
641
      {
642
      DistortedObject.debugLists();
643
      }
644
*/
645
    // mark OpenGL state as unknown
646 599
    DistortedRenderState.reset();
647 600

  
648
    int numRenders=0;
601
    int numRenders=0, numChildren = mChildren.getNumChildren();
649 602

  
650
    for(int i=0; i<mNumChildren; i++)
603
    for(int i=0; i<numChildren; i++)
651 604
      {
652
      numRenders += mChildren.get(i).renderRecursive(time);
605
      numRenders += mChildren.getChild(i).renderRecursive(time);
653 606
      }
654 607

  
655
    numRenders += renderChildren(time,mNumChildren,mChildren,fbo, mRenderWayOIT);
608
    numRenders += renderChildren(time,numChildren,mChildren,fbo, mRenderWayOIT);
656 609

  
657 610
    return numRenders;
658 611
    }
......
927 880
 */
928 881
  public void attach(DistortedNode node)
929 882
    {
930
    mJobs.add(new Job(ATTACH,node));
931
    DistortedMaster.newSlave(this);
883
    mChildren.attach(node);
932 884
    }
933 885

  
934 886
///////////////////////////////////////////////////////////////////////////////////////////////////
......
945 897
 */
946 898
  public DistortedNode attach(DistortedSurface surface, DistortedEffects effects, MeshBase mesh)
947 899
    {
948
    DistortedNode node = new DistortedNode(surface,effects,mesh);
949
    mJobs.add(new Job(ATTACH,node));
950
    DistortedMaster.newSlave(this);
951
    return node;
900
    return mChildren.attach(surface,effects,mesh);
952 901
    }
953 902

  
954 903
///////////////////////////////////////////////////////////////////////////////////////////////////
......
965 914
 */
966 915
  public void detach(DistortedEffects effects)
967 916
    {
968
    long id = effects.getID();
969
    DistortedNode node;
970
    boolean detached = false;
971

  
972
    for(int i=0; i<mNumChildren; i++)
973
      {
974
      node = mChildren.get(i);
975

  
976
      if( node.getEffects().getID()==id )
977
        {
978
        detached = true;
979
        mJobs.add(new Job(DETACH,node));
980
        DistortedMaster.newSlave(this);
981
        break;
982
        }
983
      }
984

  
985
    if( !detached )
986
      {
987
      // if we failed to detach any, it still might be the case that
988
      // there's an ATTACH job that we need to cancel.
989
      int num = mJobs.size();
990
      Job job;
991

  
992
      for(int i=0; i<num; i++)
993
        {
994
        job = mJobs.get(i);
995

  
996
        if( job.type==ATTACH && job.node.getEffects()==effects )
997
          {
998
          mJobs.remove(i);
999
          break;
1000
          }
1001
        }
1002
      }
917
    mChildren.detach(effects);
1003 918
    }
1004 919

  
1005 920
///////////////////////////////////////////////////////////////////////////////////////////////////
......
1013 928
 */
1014 929
  public void detach(DistortedNode node)
1015 930
    {
1016
    mJobs.add(new Job(DETACH,node));
1017
    DistortedMaster.newSlave(this);
931
    mChildren.detach(node);
1018 932
    }
1019 933

  
1020 934
///////////////////////////////////////////////////////////////////////////////////////////////////
......
1026 940
 */
1027 941
  public void detachAll()
1028 942
    {
1029
    mJobs.add(new Job(DETALL,null));
1030
    DistortedMaster.newSlave(this);
1031
    }
1032

  
1033
///////////////////////////////////////////////////////////////////////////////////////////////////
1034
/**
1035
 * This is not really part of the public API. Has to be public only because it is a part of the
1036
 * DistortedSlave interface, which should really be a class that we extend here instead but
1037
 * Java has no multiple inheritance.
1038
 *
1039
 * @y.exclude
1040
 */
1041
  public void doWork()
1042
    {
1043
    int num = mJobs.size();
1044

  
1045
    if( num>0 )
1046
      {
1047
      Job job;
1048

  
1049
      for(int i=0; i<num; i++)
1050
        {
1051
        job = mJobs.remove(0);
1052

  
1053
        switch(job.type)
1054
          {
1055
          case ATTACH: if( mChildren==null ) mChildren = new ArrayList<>(2);
1056
                       job.node.setSurfaceParent(this);
1057
                       DistortedMaster.addSortingByBuckets(mChildren,job.node);
1058
                       mNumChildren++;
1059
                       break;
1060
          case DETACH: if( mNumChildren>0 && mChildren.remove(job.node) )
1061
                         {
1062
                         job.node.setSurfaceParent(null);
1063
                         mNumChildren--;
1064
                         }
1065
                       break;
1066
          case DETALL: if( mNumChildren>0 )
1067
                         {
1068
                         DistortedNode tmp;
1069

  
1070
                         for(int j=mNumChildren-1; j>=0; j--)
1071
                           {
1072
                           tmp = mChildren.remove(j);
1073
                           tmp.setSurfaceParent(null);
1074
                           }
1075

  
1076
                         mNumChildren = 0;
1077
                         }
1078
                       break;
1079
          case SORT  : mChildren.remove(job.node);
1080
                       DistortedMaster.addSortingByBuckets(mChildren,job.node);
1081
                       break;
1082
          }
1083
        }
1084
      }
943
    mChildren.detachAll();
1085 944
    }
1086 945
}
src/main/java/org/distorted/library/main/EffectQueue.java
126 126

  
127 127
    int numNodes = (mNodes==null ? 0: mNodes.size());
128 128
    for(int i=0; i<numNodes; i++) mNodes.get(i).sort();
129

  
130
/*
131
    if( mIndex == EffectType.MATRIX.ordinal() )
132
      android.util.Log.d("queue", "queueM id="+mID);
133
    if( mIndex == EffectType.VERTEX.ordinal() )
134
      android.util.Log.d("queue", "queueV id="+mID);
135
    if( mIndex == EffectType.FRAGMENT.ordinal() )
136
      android.util.Log.d("queue", "queueF id="+mID);
137
    if( mIndex == EffectType.POSTPROCESS.ordinal() )
138
      android.util.Log.d("queue", "queueP id="+mID);
139
*/
140 129
    }
141 130

  
142 131
///////////////////////////////////////////////////////////////////////////////////////////////////
......
341 330
 */
342 331
  public void doWork()
343 332
    {
333
    boolean changed = false;
344 334
    int num = mJobs.size();
345 335
    Job job;
346 336

  
......
351 341
      switch(job.type)
352 342
        {
353 343
        case CREATE: int max = mMax[mIndex];
354

  
355 344
                     if( max>0 )
356 345
                       {
357 346
                       mUniforms        = new float[max*job.num];
......
368 357
                       mEffects[mNumEffects] = job.effect;
369 358
                       mName[mNumEffects] = job.effect.getName().ordinal();
370 359
                       mNumEffects++;
360
                       changed = true;
371 361
                       }
372 362
                     else
373 363
                       {
......
379 369
                       if (mEffects[j] == job.effect)
380 370
                         {
381 371
                         remove(j);
372
                         changed = true;
382 373
                         break;
383 374
                         }
384 375
                       }
385 376
                     break;
386 377
        case DETALL: for(int j=0; j<mNumEffects; j++ )
387 378
                       {
379
                       changed = true;
380

  
388 381
                       if( job.notify )
389 382
                         {
390 383
                         for(int k=0; k<mNumListeners; k++)
......
399 392
        }
400 393
      }
401 394

  
402
    if( num>0 && mIndex==EffectType.POSTPROCESS.ordinal() ) regenerateIDandSort();
395
    if( changed && mIndex==EffectType.POSTPROCESS.ordinal() ) regenerateIDandSort();
403 396
    }
404 397
  }

Also available in: Unified diff