Project

General

Profile

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

library / src / main / java / org / distorted / library / main / DistortedEffects.java @ 2f35828c

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 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.Effect;
28
import org.distorted.library.effect.EffectName;
29
import org.distorted.library.effect.EffectType;
30
import org.distorted.library.effect.FragmentEffect;
31
import org.distorted.library.effect.VertexEffect;
32
import org.distorted.library.message.EffectListener;
33
import org.distorted.library.program.DistortedProgram;
34
import org.distorted.library.program.FragmentCompilationException;
35
import org.distorted.library.program.FragmentUniformsException;
36
import org.distorted.library.program.LinkingException;
37
import org.distorted.library.program.VertexCompilationException;
38
import org.distorted.library.program.VertexUniformsException;
39

    
40
import java.io.InputStream;
41
import java.nio.ByteBuffer;
42
import java.nio.ByteOrder;
43
import java.nio.FloatBuffer;
44
import java.nio.IntBuffer;
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47
/**
48
 * Class containing Matrix, Vertex, Fragment and Postprocessing effect queues.
49
 * <p>
50
 * The queues hold actual effects to be applied to a given (InputSurface,MeshObject) combo.
51
 */
52
public class DistortedEffects
53
  {
54
  /// MAIN PROGRAM ///
55
  private static DistortedProgram mMainProgram;
56
  private static int mMainTextureH;
57

    
58
  /// BLIT PROGRAM ///
59
  private static DistortedProgram mBlitProgram;
60
  private static int mBlitTextureH;
61
  private static int mBlitDepthH;
62
  private static final FloatBuffer mQuadPositions;
63

    
64
  static
65
    {
66
    float[] positionData= { -0.5f, -0.5f,  -0.5f, 0.5f,  0.5f,-0.5f,  0.5f, 0.5f };
67
    mQuadPositions = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder()).asFloatBuffer();
68
    mQuadPositions.put(positionData).position(0);
69
    }
70

    
71
  /// BLIT DEPTH PROGRAM ///
72
  private static DistortedProgram mBlitDepthProgram;
73
  private static int mBlitDepthTextureH;
74
  private static int mBlitDepthDepthTextureH;
75
  private static int mBlitDepthDepthH;
76
  private static int mBlitDepthTexCorrH;
77
  private static int mBlitDepthSizeH;
78
  private static int mBlitDepthNumRecordsH;
79

    
80
  private static int[] mLinkedListSSBO = new int[1];
81
  private static int[] mAtomicCounter = new int[1];
82

    
83
  static
84
    {
85
    mLinkedListSSBO[0]= -1;
86
    mAtomicCounter[0] = -1;
87
    }
88

    
89
  private static int mBufferSize=(0x1<<23);  // 8 million entries
90

    
91
  private static IntBuffer mIntBuffer;
92

    
93
private static ByteBuffer mBuf;
94
private static IntBuffer mIntBuf;
95

    
96
  /// BLIT DEPTH RENDER PROGRAM ///
97
  private static DistortedProgram mBlitDepthRenderProgram;
98
  private static int mBlitDepthRenderDepthTextureH;
99
  private static int mBlitDepthRenderDepthH;
100
  private static int mBlitDepthRenderTexCorrH;
101
  private static int mBlitDepthRenderSizeH;
102

    
103
  /// NORMAL PROGRAM /////
104
  private static DistortedProgram mNormalProgram;
105
  private static int mNormalMVPMatrixH;
106
  /// END PROGRAMS //////
107

    
108
  private static long mNextID =0;
109
  private long mID;
110

    
111
  private EffectQueueMatrix mM;
112
  private EffectQueueFragment mF;
113
  private EffectQueueVertex mV;
114
  private EffectQueuePostprocess mP;
115

    
116
  private boolean matrixCloned, vertexCloned, fragmentCloned, postprocessCloned;
117

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

    
120
  static void createProgram(Resources resources)
121
  throws FragmentCompilationException,VertexCompilationException,VertexUniformsException,FragmentUniformsException,LinkingException
122
    {
123
    // MAIN PROGRAM ////////////////////////////////////
124
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
125
    final InputStream mainFragStream = resources.openRawResource(R.raw.main_fragment_shader);
126

    
127
    int numF = FragmentEffect.getNumEnabled();
128
    int numV = VertexEffect.getNumEnabled();
129

    
130
    String mainVertHeader= Distorted.GLSL_VERSION + ("#define NUM_VERTEX "   + ( numV>0 ? getMax(EffectType.VERTEX  ) : 0 ) + "\n");
131
    String mainFragHeader= Distorted.GLSL_VERSION + ("#define NUM_FRAGMENT " + ( numF>0 ? getMax(EffectType.FRAGMENT) : 0 ) + "\n");
132
    String enabledEffectV= VertexEffect.getGLSL();
133
    String enabledEffectF= FragmentEffect.getGLSL();
134

    
135
    //android.util.Log.e("Effects", "vertHeader= "+mainVertHeader);
136
    //android.util.Log.e("Effects", "fragHeader= "+mainFragHeader);
137
    //android.util.Log.e("Effects", "enabledV= "+enabledEffectV);
138
    //android.util.Log.e("Effects", "enabledF= "+enabledEffectF);
139

    
140
    String[] feedback = { "v_Position", "v_endPosition" };
141

    
142
    try
143
      {
144
      mMainProgram = new DistortedProgram(mainVertStream, mainFragStream, mainVertHeader, mainFragHeader,
145
                                          enabledEffectV, enabledEffectF, Distorted.GLSL, feedback);
146
      }
147
    catch(Exception e)
148
      {
149
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile MAIN program: "+e.getMessage());
150
      throw new RuntimeException(e.getMessage());
151
      }
152

    
153
    int mainProgramH = mMainProgram.getProgramHandle();
154
    EffectQueueFragment.getUniforms(mainProgramH);
155
    EffectQueueVertex.getUniforms(mainProgramH);
156
    EffectQueueMatrix.getUniforms(mainProgramH);
157
    mMainTextureH= GLES31.glGetUniformLocation( mainProgramH, "u_Texture");
158

    
159
    // BLIT PROGRAM ////////////////////////////////////
160
    final InputStream blitVertStream = resources.openRawResource(R.raw.blit_vertex_shader);
161
    final InputStream blitFragStream = resources.openRawResource(R.raw.blit_fragment_shader);
162

    
163
    String blitVertHeader= (Distorted.GLSL_VERSION + "#define NUM_VERTEX 0\n"  );
164
    String blitFragHeader= (Distorted.GLSL_VERSION + "#define NUM_FRAGMENT 0\n");
165

    
166
    try
167
      {
168
      mBlitProgram = new DistortedProgram(blitVertStream,blitFragStream,blitVertHeader,blitFragHeader, Distorted.GLSL);
169
      }
170
    catch(Exception e)
171
      {
172
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile BLIT program: "+e.getMessage());
173
      throw new RuntimeException(e.getMessage());
174
      }
175

    
176
    int blitProgramH = mBlitProgram.getProgramHandle();
177
    mBlitTextureH  = GLES31.glGetUniformLocation( blitProgramH, "u_Texture");
178
    mBlitDepthH    = GLES31.glGetUniformLocation( blitProgramH, "u_Depth");
179

    
180
    // BLIT DEPTH PROGRAM ////////////////////////////////////
181
    final InputStream blitDepthVertStream = resources.openRawResource(R.raw.blit_depth_vertex_shader);
182
    final InputStream blitDepthFragStream = resources.openRawResource(R.raw.blit_depth_fragment_shader);
183

    
184
    try
185
      {
186
      mBlitDepthProgram = new DistortedProgram(blitDepthVertStream,blitDepthFragStream,blitVertHeader,blitFragHeader, Distorted.GLSL);
187
      }
188
    catch(Exception e)
189
      {
190
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile BLIT DEPTH program: "+e.getMessage());
191
      throw new RuntimeException(e.getMessage());
192
      }
193

    
194
    int blitDepthProgramH   = mBlitDepthProgram.getProgramHandle();
195
    mBlitDepthTextureH      = GLES31.glGetUniformLocation( blitDepthProgramH, "u_Texture");
196
    mBlitDepthDepthTextureH = GLES31.glGetUniformLocation( blitDepthProgramH, "u_DepthTexture");
197
    mBlitDepthDepthH        = GLES31.glGetUniformLocation( blitDepthProgramH, "u_Depth");
198
    mBlitDepthTexCorrH      = GLES31.glGetUniformLocation( blitDepthProgramH, "u_TexCorr");
199
    mBlitDepthSizeH         = GLES31.glGetUniformLocation( blitDepthProgramH, "u_Size");
200
    mBlitDepthNumRecordsH   = GLES31.glGetUniformLocation( blitDepthProgramH, "u_numRecords");
201

    
202
    mIntBuffer = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
203
    mIntBuffer.put(0,0);
204

    
205
    if( mLinkedListSSBO[0]<0 )
206
      {
207
      GLES31.glGenBuffers(1,mLinkedListSSBO,0);
208
      GLES31.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
209
      GLES31.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, mBufferSize*4 , null, GLES31.GL_DYNAMIC_READ|GLES31.GL_DYNAMIC_DRAW);
210

    
211
      mBuf = (ByteBuffer)GLES31.glMapBufferRange(GLES31.GL_SHADER_STORAGE_BUFFER, 0, mBufferSize*4, GLES31.GL_MAP_READ_BIT);
212
      mIntBuf = mBuf.order(ByteOrder.nativeOrder()).asIntBuffer();
213

    
214
      GLES31.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 1, mLinkedListSSBO[0]);
215
      }
216

    
217
    if( mAtomicCounter[0]<0 )
218
      {
219
      GLES31.glGenBuffers(1,mAtomicCounter,0);
220
      GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, mAtomicCounter[0] );
221
      GLES31.glBufferData(GLES31.GL_ATOMIC_COUNTER_BUFFER, 4, mIntBuffer, GLES31.GL_DYNAMIC_DRAW);
222
      GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, 0);
223
      }
224

    
225
    // BLIT DEPTH RENDER PROGRAM ///////////////////////////
226
    final InputStream blitDepthRenderVertStream = resources.openRawResource(R.raw.blit_depth_vertex_shader);
227
    final InputStream blitDepthRenderFragStream = resources.openRawResource(R.raw.blit_depth_render_fragment_shader);
228

    
229
    try
230
      {
231
      mBlitDepthRenderProgram = new DistortedProgram(blitDepthRenderVertStream,blitDepthRenderFragStream,blitVertHeader,blitFragHeader, Distorted.GLSL);
232
      }
233
    catch(Exception e)
234
      {
235
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile BLIT DEPTH RENDER program: "+e.getMessage());
236
      throw new RuntimeException(e.getMessage());
237
      }
238

    
239
    int blitDepthRenderProgramH   = mBlitDepthRenderProgram.getProgramHandle();
240
    mBlitDepthRenderDepthTextureH = GLES31.glGetUniformLocation( blitDepthRenderProgramH, "u_DepthTexture");
241
    mBlitDepthRenderDepthH        = GLES31.glGetUniformLocation( blitDepthRenderProgramH, "u_Depth");
242
    mBlitDepthRenderTexCorrH      = GLES31.glGetUniformLocation( blitDepthRenderProgramH, "u_TexCorr");
243
    mBlitDepthRenderSizeH         = GLES31.glGetUniformLocation( blitDepthRenderProgramH, "u_Size");
244

    
245
    // NORMAL PROGRAM //////////////////////////////////////
246
    final InputStream normalVertexStream   = resources.openRawResource(R.raw.normal_vertex_shader);
247
    final InputStream normalFragmentStream = resources.openRawResource(R.raw.normal_fragment_shader);
248

    
249
    try
250
      {
251
      mNormalProgram = new DistortedProgram(normalVertexStream,normalFragmentStream, Distorted.GLSL_VERSION, Distorted.GLSL_VERSION, Distorted.GLSL);
252
      }
253
    catch(Exception e)
254
      {
255
      Log.e("EFFECTS", e.getClass().getSimpleName()+" trying to compile NORMAL program: "+e.getMessage());
256
      throw new RuntimeException(e.getMessage());
257
      }
258

    
259
    int normalProgramH = mNormalProgram.getProgramHandle();
260
    mNormalMVPMatrixH  = GLES31.glGetUniformLocation( normalProgramH, "u_MVPMatrix");
261
    }
262

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

    
265
  private void initializeEffectLists(DistortedEffects d, int flags)
266
    {
267
    if( (flags & Distorted.CLONE_MATRIX) != 0 )
268
      {
269
      mM = d.mM;
270
      matrixCloned = true;
271
      }
272
    else
273
      {
274
      mM = new EffectQueueMatrix(mID);
275
      matrixCloned = false;
276
      }
277
    
278
    if( (flags & Distorted.CLONE_VERTEX) != 0 )
279
      {
280
      mV = d.mV;
281
      vertexCloned = true;
282
      }
283
    else
284
      {
285
      mV = new EffectQueueVertex(mID);
286
      vertexCloned = false;
287
      }
288
    
289
    if( (flags & Distorted.CLONE_FRAGMENT) != 0 )
290
      {
291
      mF = d.mF;
292
      fragmentCloned = true;
293
      }
294
    else
295
      {
296
      mF = new EffectQueueFragment(mID);
297
      fragmentCloned = false;
298
      }
299

    
300
    if( (flags & Distorted.CLONE_POSTPROCESS) != 0 )
301
      {
302
      mP = d.mP;
303
      postprocessCloned = true;
304
      }
305
    else
306
      {
307
      mP = new EffectQueuePostprocess(mID);
308
      postprocessCloned = false;
309
      }
310
    }
311

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313

    
314
  EffectQueuePostprocess getPostprocess()
315
    {
316
    return mP;
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  void newNode(DistortedNode node)
322
    {
323
    mM.newNode(node);
324
    mF.newNode(node);
325
    mV.newNode(node);
326
    mP.newNode(node);
327
    }
328

    
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330

    
331
  private void displayNormals(MeshObject mesh)
332
    {
333
    GLES31.glBindBufferBase(GLES31.GL_TRANSFORM_FEEDBACK_BUFFER, 0, mesh.mAttTFO[0]);
334
    GLES31.glBeginTransformFeedback( GLES31.GL_POINTS);
335
    DistortedRenderState.switchOffDrawing();
336
    GLES31.glDrawArrays( GLES31.GL_POINTS, 0, mesh.numVertices);
337
    DistortedRenderState.restoreDrawing();
338
    GLES31.glEndTransformFeedback();
339
    GLES31.glBindBufferBase(GLES31.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
340

    
341
    mNormalProgram.useProgram();
342
    GLES31.glUniformMatrix4fv(mNormalMVPMatrixH, 1, false, mM.getMVP() , 0);
343
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, mesh.mAttTFO[0]);
344
    GLES31.glVertexAttribPointer(mNormalProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, 0, 0);
345
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
346
    GLES31.glLineWidth(8.0f);
347
    GLES31.glDrawArrays(GLES31.GL_LINES, 0, 2*mesh.numVertices);
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  void drawPriv(float halfW, float halfH, MeshObject mesh, DistortedOutputSurface surface, long currTime, float marginInPixels)
353
    {
354
    float halfZ = halfW*mesh.zFactor;
355

    
356
    mM.compute(currTime);
357
    mV.compute(currTime,halfW,halfH,halfZ);
358
    mF.compute(currTime,halfW,halfH);
359
    mP.compute(currTime);
360

    
361
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
362

    
363
    mMainProgram.useProgram();
364
    GLES31.glUniform1i(mMainTextureH, 0);
365

    
366
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, mesh.mAttVBO[0]);
367
    GLES31.glVertexAttribPointer(mMainProgram.mAttribute[0], MeshObject.POS_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET0);
368
    GLES31.glVertexAttribPointer(mMainProgram.mAttribute[1], MeshObject.NOR_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET1);
369
    GLES31.glVertexAttribPointer(mMainProgram.mAttribute[2], MeshObject.TEX_DATA_SIZE, GLES31.GL_FLOAT, false, MeshObject.VERTSIZE, MeshObject.OFFSET2);
370
    GLES31.glBindBuffer(GLES31.GL_ARRAY_BUFFER, 0);
371

    
372
    mM.send(surface,halfW,halfH,halfZ,marginInPixels);
373
    mV.send();
374
    mF.send();
375

    
376
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, mesh.numVertices);
377

    
378
    if( mesh.mShowNormals ) displayNormals(mesh);
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382
/**
383
 * Only for use by the library itself.
384
 *
385
 * @y.exclude
386
 */
387
  public static void blitPriv(DistortedOutputSurface surface)
388
    {
389
    mBlitProgram.useProgram();
390

    
391
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
392
    GLES31.glUniform1i(mBlitTextureH, 0);
393
    GLES31.glUniform1f( mBlitDepthH , 1.0f-surface.mNear);
394
    GLES31.glVertexAttribPointer(mBlitProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
395
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  static void blitDepthPriv(DistortedOutputSurface surface, float corrW, float corrH)
401
    {
402
    mBlitDepthProgram.useProgram();
403

    
404
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
405
    GLES31.glUniform1i(mBlitDepthTextureH, 0);
406
    GLES31.glUniform1i(mBlitDepthDepthTextureH, 1);
407
    GLES31.glUniform2f(mBlitDepthTexCorrH, corrW, corrH );
408
    GLES31.glUniform2i(mBlitDepthSizeH, surface.mWidth, surface.mHeight);
409
    GLES31.glUniform1ui(mBlitDepthNumRecordsH, (mBufferSize-surface.mWidth*surface.mHeight)/3 );  // see the fragment shader
410
    GLES31.glUniform1f(mBlitDepthDepthH , 1.0f-surface.mNear);
411
    GLES31.glVertexAttribPointer(mBlitDepthProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
412
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416
// render all the transparent pixels from the per-pixel linked lists. This is in the 'merge
417
// postprocessing buckets' stage.
418

    
419
  static void blitDepthRenderPriv(DistortedOutputSurface surface, float corrW, float corrH)
420
    {
421
    mBlitDepthRenderProgram.useProgram();
422

    
423
    analyzeBuffer(surface.mWidth, surface.mHeight);
424

    
425
    GLES31.glViewport(0, 0, surface.mWidth, surface.mHeight );
426
    GLES31.glUniform1i(mBlitDepthRenderDepthTextureH, 1);
427
    GLES31.glUniform2f(mBlitDepthRenderTexCorrH, corrW, corrH );
428
    GLES31.glUniform2i(mBlitDepthRenderSizeH, surface.mWidth, surface.mHeight);
429
    GLES31.glUniform1f( mBlitDepthRenderDepthH , 1.0f-surface.mNear);
430
    GLES31.glVertexAttribPointer(mBlitDepthRenderProgram.mAttribute[0], 2, GLES31.GL_FLOAT, false, 0, mQuadPositions);
431
    GLES31.glDrawArrays(GLES31.GL_TRIANGLE_STRIP, 0, 4);
432

    
433
    // reset atomic counter to 0
434
    GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, mAtomicCounter[0] );
435
    GLES31.glBufferData(GLES31.GL_ATOMIC_COUNTER_BUFFER, 4, mIntBuffer, GLES31.GL_DYNAMIC_DRAW);
436
    GLES31.glBindBuffer(GLES31.GL_ATOMIC_COUNTER_BUFFER, 0);
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441

    
442
  private static void analyzeBuffer(int w, int h)
443
    {
444
    int ptr;
445
    final int GREEN = (255<<16) + 255;
446
    final int RED   = (255<<24) + 255;
447

    
448
    int left1=0, left2=0;
449
    int right1=0, right2=0;
450
    int overflow = 0;
451

    
452
    for(int row=0; row<h; row++)
453
      for(int col=0; col<w; col++)
454
        {
455
        ptr = mIntBuf.get( col+row*w );
456

    
457
        if( ptr!=0 )
458
          {
459
          if( ptr>0 && ptr<mBufferSize )
460
            {
461
            ptr = mIntBuf.get(ptr);
462

    
463
            if ((2*col>w) && ptr != RED)
464
              {
465
              if (ptr==GREEN) right1++;
466
              else            right2++;
467
              }
468
            if ((2*col<=w) && ptr != GREEN)
469
              {
470
              if (ptr==RED) left1++;
471
              else          left2++;
472
              }
473
            }
474
          else
475
            {
476
            overflow++;
477
            }
478
          }
479
        }
480

    
481
    android.util.Log.e("surface", " left1: "+left1+" left2: "+left2+" right1: "+right1+" right2: "+right2+" overflow: "+overflow);
482
    }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485

    
486
  private void releasePriv()
487
    {
488
    if( !matrixCloned   )   mM.abortAll(false);
489
    if( !vertexCloned   )   mV.abortAll(false);
490
    if( !fragmentCloned )   mF.abortAll(false);
491
    if( !postprocessCloned) mP.abortAll(false);
492

    
493
    mM = null;
494
    mV = null;
495
    mF = null;
496
    mP = null;
497
    }
498

    
499
///////////////////////////////////////////////////////////////////////////////////////////////////
500

    
501
  static void onDestroy()
502
    {
503
    mNextID           =  0;
504
    mLinkedListSSBO[0]= -1;
505
    mAtomicCounter[0] = -1;
506
    }
507

    
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509
// PUBLIC API
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511
/**
512
 * Create empty effect queue.
513
 */
514
  public DistortedEffects()
515
    {
516
    mID = ++mNextID;
517
    initializeEffectLists(this,0);
518
    }
519

    
520
///////////////////////////////////////////////////////////////////////////////////////////////////
521
/**
522
 * Copy constructor.
523
 * <p>
524
 * Whatever we do not clone gets created just like in the default constructor.
525
 *
526
 * @param dc    Source object to create our object from
527
 * @param flags A bitmask of values specifying what to copy.
528
 *              For example, CLONE_VERTEX | CLONE_MATRIX.
529
 */
530
  public DistortedEffects(DistortedEffects dc, int flags)
531
    {
532
    mID = ++mNextID;
533
    initializeEffectLists(dc,flags);
534
    }
535

    
536
///////////////////////////////////////////////////////////////////////////////////////////////////
537
/**
538
 * Releases all resources. After this call, the queue should not be used anymore.
539
 */
540
  @SuppressWarnings("unused")
541
  public synchronized void delete()
542
    {
543
    releasePriv();
544
    }
545

    
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547
/**
548
 * Returns unique ID of this instance.
549
 *
550
 * @return ID of the object.
551
 */
552
  public long getID()
553
      {
554
      return mID;
555
      }
556

    
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558
/**
559
 * Adds the calling class to the list of Listeners that get notified each time some event happens 
560
 * to one of the Effects in our queues. Nothing will happen if 'el' is already in the list.
561
 * 
562
 * @param el A class implementing the EffectListener interface that wants to get notifications.
563
 */
564
  @SuppressWarnings("unused")
565
  public void registerForMessages(EffectListener el)
566
    {
567
    mM.registerForMessages(el);
568
    mV.registerForMessages(el);
569
    mF.registerForMessages(el);
570
    mP.registerForMessages(el);
571
    }
572

    
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574
/**
575
 * Removes the calling class from the list of Listeners that get notified if something happens to Effects in our queue.
576
 * 
577
 * @param el A class implementing the EffectListener interface that no longer wants to get notifications.
578
 */
579
  @SuppressWarnings("unused")
580
  public void deregisterForMessages(EffectListener el)
581
    {
582
    mM.deregisterForMessages(el);
583
    mV.deregisterForMessages(el);
584
    mF.deregisterForMessages(el);
585
    mP.deregisterForMessages(el);
586
    }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589
/**
590
 * Aborts all Effects.
591
 * @return Number of effects aborted.
592
 */
593
  public int abortAllEffects()
594
    {
595
    return mM.abortAll(true) + mV.abortAll(true) + mF.abortAll(true);
596
    }
597

    
598
///////////////////////////////////////////////////////////////////////////////////////////////////
599
/**
600
 * Aborts all Effects of a given type, for example all MATRIX Effects.
601
 * 
602
 * @param type one of the constants defined in {@link EffectType}
603
 * @return Number of effects aborted.
604
 */
605
  public int abortByType(EffectType type)
606
    {
607
    switch(type)
608
      {
609
      case MATRIX     : return mM.abortAll(true);
610
      case VERTEX     : return mV.abortAll(true);
611
      case FRAGMENT   : return mF.abortAll(true);
612
      case POSTPROCESS: return mP.abortAll(true);
613
      default         : return 0;
614
      }
615
    }
616

    
617
///////////////////////////////////////////////////////////////////////////////////////////////////
618
/**
619
 * Aborts an Effect by its ID.
620
 *
621
 * @param id the Id of the Effect to be removed, as returned by getID().
622
 * @return Number of effects aborted.
623
 */
624
  public int abortById(long id)
625
    {
626
    long type = id&EffectType.MASK;
627

    
628
    if( type == EffectType.MATRIX.ordinal()      ) return mM.removeById(id);
629
    if( type == EffectType.VERTEX.ordinal()      ) return mV.removeById(id);
630
    if( type == EffectType.FRAGMENT.ordinal()    ) return mF.removeById(id);
631
    if( type == EffectType.POSTPROCESS.ordinal() ) return mP.removeById(id);
632

    
633
    return 0;
634
    }
635

    
636
///////////////////////////////////////////////////////////////////////////////////////////////////
637
/**
638
 * Aborts a single Effect.
639
 * 
640
 * @param effect the Effect we want to abort.
641
 * @return number of Effects aborted. Always either 0 or 1.
642
 */
643
  public int abortEffect(Effect effect)
644
    {
645
    switch(effect.getType())
646
      {
647
      case MATRIX     : return mM.removeEffect(effect);
648
      case VERTEX     : return mV.removeEffect(effect);
649
      case FRAGMENT   : return mF.removeEffect(effect);
650
      case POSTPROCESS: return mP.removeEffect(effect);
651
      default         : return 0;
652
      }
653
    }
654

    
655
///////////////////////////////////////////////////////////////////////////////////////////////////
656
/**
657
 * Abort all Effects of a given name, for example all rotations.
658
 * 
659
 * @param name one of the constants defined in {@link EffectName}
660
 * @return number of Effects aborted.
661
 */
662
  public int abortByName(EffectName name)
663
    {
664
    switch(name.getType())
665
      {
666
      case MATRIX     : return mM.removeByName(name);
667
      case VERTEX     : return mV.removeByName(name);
668
      case FRAGMENT   : return mF.removeByName(name);
669
      case POSTPROCESS: return mP.removeByName(name);
670
      default                : return 0;
671
      }
672
    }
673

    
674
///////////////////////////////////////////////////////////////////////////////////////////////////
675
/**
676
 * Returns the maximum number of effects of a given type that can be simultaneously applied to a
677
 * single (InputSurface,MeshObject) combo.
678
 *
679
 * @param type {@link EffectType}
680
 * @return The maximum number of effects of a given type.
681
 */
682
  @SuppressWarnings("unused")
683
  public static int getMax(EffectType type)
684
    {
685
    return EffectQueue.getMax(type.ordinal());
686
    }
687

    
688
///////////////////////////////////////////////////////////////////////////////////////////////////
689
/**
690
 * Sets the maximum number of effects that can be stored in a single EffectQueue at one time.
691
 * This can fail if:
692
 * <ul>
693
 * <li>the value of 'max' is outside permitted range (0 &le; max &le; Byte.MAX_VALUE)
694
 * <li>We try to increase the value of 'max' when it is too late to do so already. It needs to be called
695
 *     before the Vertex Shader gets compiled, i.e. before the call to {@link Distorted#onCreate}. After this
696
 *     time only decreasing the value of 'max' is permitted.
697
 * <li>Furthermore, this needs to be called before any instances of the DistortedEffects class get created.
698
 * </ul>
699
 *
700
 * @param type {@link EffectType}
701
 * @param max new maximum number of simultaneous effects. Has to be a non-negative number not greater
702
 *            than Byte.MAX_VALUE
703
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
704
 */
705
  @SuppressWarnings("unused")
706
  public static boolean setMax(EffectType type, int max)
707
    {
708
    return EffectQueue.setMax(type.ordinal(),max);
709
    }
710

    
711
///////////////////////////////////////////////////////////////////////////////////////////////////
712
/**
713
 * Add a new Effect to our queue.
714
 *
715
 * @param effect The Effect to add.
716
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
717
 */
718
  public boolean apply(Effect effect)
719
    {
720
    switch(effect.getType())
721
      {
722
      case MATRIX      : return mM.add(effect);
723
      case VERTEX      : return mV.add(effect);
724
      case FRAGMENT    : return mF.add(effect);
725
      case POSTPROCESS : return mP.add(effect);
726
      }
727

    
728
    return false;
729
    }
730
  }
(2-2/21)