Project

General

Profile

« Previous | Next » 

Revision 7f92dd3a

Added by Leszek Koltunski 5 days ago

Rename .java to .kt

View differences:

src/main/java/org/distorted/library/main/DistortedEffects.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library 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 GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.main;
22

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

  
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29
/**
30
 * Class containing Matrix, Vertex, Fragment and Postprocessing effect queues.
31
 * <p>
32
 * The queues hold actual effects to be applied to a given (InputSurface,MeshBase) combo.
33
 */
34
public class DistortedEffects
35
  {
36
  private final long mID;
37
  private final EffectQueue[] mQueues;
38

  
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40
/**
41
 * @y.exclude
42
 */
43
  public EffectQueue[] getQueues()
44
    {
45
    return mQueues;
46
    }
47

  
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49
// PUBLIC API
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
/**
52
 * Create empty effect queue.
53
 */
54
 public DistortedEffects()
55
    {
56
    mID = InternalStackFrameList.getNextEffectsID();
57
    mQueues = EffectQueue.createQueues();
58
    }
59

  
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61
/**
62
 * Copy constructor.
63
 * <p>
64
 * Whatever we do not clone gets created just like in the default constructor.
65
 *
66
 * @param dc    Source object to create our object from
67
 * @param flags A bitmask of values specifying what to copy.
68
 *              For example, CLONE_VERTEX | CLONE_MATRIX.
69
 */
70
  public DistortedEffects(DistortedEffects dc, int flags)
71
    {
72
    mID = InternalStackFrameList.getNextEffectsID();
73
    mQueues = EffectQueue.createQueues(dc.getQueues(),flags);
74
    }
75

  
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77
/**
78
 * Returns unique ID of this instance.
79
 *
80
 * @return ID of the object.
81
 */
82
  public long getID()
83
      {
84
      return mID;
85
      }
86

  
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88
/**
89
 * Return if this queue contains effect with a given ID.
90
 */
91
  public boolean exists(long id)
92
    {
93
    int num = (int)(id&EffectType.MASK);
94
    return mQueues[num].exists(id);
95
    }
96

  
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
/**
99
 * Aborts all Effects.
100
 * @return Number of effects aborted.
101
 */
102
  public int abortAllEffects()
103
    {
104
    int aborted = 0;
105

  
106
    for( int i=0; i<EffectType.LENGTH; i++)
107
      {
108
      aborted += mQueues[i].removeAll(true);
109
      }
110

  
111
    return aborted;
112
    }
113

  
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115
/**
116
 * Aborts all Effects of a given type, for example all MATRIX Effects.
117
 * 
118
 * @param type one of the constants defined in {@link EffectType}
119
 * @return Number of effects aborted.
120
 */
121
  public int abortByType(EffectType type)
122
    {
123
    int num = type.ordinal();
124
    return mQueues[num].removeAll(true);
125
    }
126

  
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128
/**
129
 * Aborts an Effect by its ID.
130
 *
131
 * @param id the Id of the Effect to be removed, as returned by getID().
132
 * @return Number of effects aborted.
133
 */
134
  public int abortById(long id)
135
    {
136
    int num = (int)(id&EffectType.MASK);
137
    return mQueues[num].removeById(id);
138
    }
139

  
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141
/**
142
 * Aborts a single Effect.
143
 * 
144
 * @param effect the Effect we want to abort.
145
 * @return number of Effects aborted. Always either 0 or 1.
146
 */
147
  public int abortEffect(Effect effect)
148
    {
149
    int num = effect.getType().ordinal();
150
    return mQueues[num].removeEffect(effect);
151
    }
152

  
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154
/**
155
 * Abort all Effects of a given name, for example all rotations.
156
 * 
157
 * @param name one of the constants defined in {@link EffectName}
158
 * @return number of Effects aborted.
159
 */
160
  public int abortByName(EffectName name)
161
    {
162
    int num = name.getType().ordinal();
163
    return mQueues[num].removeByName(name);
164
    }
165

  
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167
/**
168
 * Add a new Effect to the tail of our queue.
169
 *
170
 * @param effect The Effect to add.
171
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
172
 */
173
  public boolean apply(Effect effect)
174
    {
175
    int num = effect.getType().ordinal();
176
    return mQueues[num].add(effect);
177
    }
178

  
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
/**
181
 * Add a new Effect to our queue at a specified position.
182
 *
183
 * @param effect The Effect to add.
184
 * @param position the place in the effects queue where to add the new effect.
185
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
186
 */
187
  public boolean apply(Effect effect, int position)
188
    {
189
    int num = effect.getType().ordinal();
190
    return mQueues[num].add(effect,position);
191
    }
192

  
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
/**
195
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
196
 */
197
  public void markForDeletion()
198
    {
199
    for( int i=0; i<EffectType.LENGTH; i++)
200
      {
201
      mQueues[i].markForDeletion();
202
      }
203
    }
204

  
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
/**
207
 * Return number of effects of the given type currently in the Queue.
208
 *
209
 * @param type The EffectType.
210
 * @return Number of effects of the given type currently in the Queue.
211
 */
212
  public int getNumEffects(EffectType type)
213
    {
214
    int num = type.ordinal();
215
    return mQueues[num].getNumEffects();
216
    }
217

  
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219
/**
220
 * Return a string describing all effects in the queues.
221
 */
222
  public String debug(int depth)
223
    {
224
    StringBuilder s = new StringBuilder();
225
    for(int i=0; i<depth; i++) s.append(" ");
226
    String space = s.toString();
227

  
228
    String mat = mQueues[0].retEffects();
229
    String ver = mQueues[1].retEffects();
230
    String fra = mQueues[2].retEffects();
231
    String pos = mQueues[3].retEffects();
232

  
233
    return space+"MAT: "+mat+"\n"+space+"VER: "+ver+"\n"+space+"FRA: "+fra+"\n"+space+"POS: "+pos;
234
    }
235
  }
src/main/java/org/distorted/library/main/DistortedEffects.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library 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 GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.main;
22

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

  
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29
/**
30
 * Class containing Matrix, Vertex, Fragment and Postprocessing effect queues.
31
 * <p>
32
 * The queues hold actual effects to be applied to a given (InputSurface,MeshBase) combo.
33
 */
34
public class DistortedEffects
35
  {
36
  private final long mID;
37
  private final EffectQueue[] mQueues;
38

  
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40
/**
41
 * @y.exclude
42
 */
43
  public EffectQueue[] getQueues()
44
    {
45
    return mQueues;
46
    }
47

  
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49
// PUBLIC API
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
/**
52
 * Create empty effect queue.
53
 */
54
 public DistortedEffects()
55
    {
56
    mID = InternalStackFrameList.getNextEffectsID();
57
    mQueues = EffectQueue.createQueues();
58
    }
59

  
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61
/**
62
 * Copy constructor.
63
 * <p>
64
 * Whatever we do not clone gets created just like in the default constructor.
65
 *
66
 * @param dc    Source object to create our object from
67
 * @param flags A bitmask of values specifying what to copy.
68
 *              For example, CLONE_VERTEX | CLONE_MATRIX.
69
 */
70
  public DistortedEffects(DistortedEffects dc, int flags)
71
    {
72
    mID = InternalStackFrameList.getNextEffectsID();
73
    mQueues = EffectQueue.createQueues(dc.getQueues(),flags);
74
    }
75

  
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77
/**
78
 * Returns unique ID of this instance.
79
 *
80
 * @return ID of the object.
81
 */
82
  public long getID()
83
      {
84
      return mID;
85
      }
86

  
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88
/**
89
 * Return if this queue contains effect with a given ID.
90
 */
91
  public boolean exists(long id)
92
    {
93
    int num = (int)(id&EffectType.MASK);
94
    return mQueues[num].exists(id);
95
    }
96

  
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
/**
99
 * Aborts all Effects.
100
 * @return Number of effects aborted.
101
 */
102
  public int abortAllEffects()
103
    {
104
    int aborted = 0;
105

  
106
    for( int i=0; i<EffectType.LENGTH; i++)
107
      {
108
      aborted += mQueues[i].removeAll(true);
109
      }
110

  
111
    return aborted;
112
    }
113

  
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115
/**
116
 * Aborts all Effects of a given type, for example all MATRIX Effects.
117
 * 
118
 * @param type one of the constants defined in {@link EffectType}
119
 * @return Number of effects aborted.
120
 */
121
  public int abortByType(EffectType type)
122
    {
123
    int num = type.ordinal();
124
    return mQueues[num].removeAll(true);
125
    }
126

  
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128
/**
129
 * Aborts an Effect by its ID.
130
 *
131
 * @param id the Id of the Effect to be removed, as returned by getID().
132
 * @return Number of effects aborted.
133
 */
134
  public int abortById(long id)
135
    {
136
    int num = (int)(id&EffectType.MASK);
137
    return mQueues[num].removeById(id);
138
    }
139

  
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141
/**
142
 * Aborts a single Effect.
143
 * 
144
 * @param effect the Effect we want to abort.
145
 * @return number of Effects aborted. Always either 0 or 1.
146
 */
147
  public int abortEffect(Effect effect)
148
    {
149
    int num = effect.getType().ordinal();
150
    return mQueues[num].removeEffect(effect);
151
    }
152

  
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154
/**
155
 * Abort all Effects of a given name, for example all rotations.
156
 * 
157
 * @param name one of the constants defined in {@link EffectName}
158
 * @return number of Effects aborted.
159
 */
160
  public int abortByName(EffectName name)
161
    {
162
    int num = name.getType().ordinal();
163
    return mQueues[num].removeByName(name);
164
    }
165

  
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167
/**
168
 * Add a new Effect to the tail of our queue.
169
 *
170
 * @param effect The Effect to add.
171
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
172
 */
173
  public boolean apply(Effect effect)
174
    {
175
    int num = effect.getType().ordinal();
176
    return mQueues[num].add(effect);
177
    }
178

  
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
/**
181
 * Add a new Effect to our queue at a specified position.
182
 *
183
 * @param effect The Effect to add.
184
 * @param position the place in the effects queue where to add the new effect.
185
 * @return <code>true</code> if operation was successful, <code>false</code> otherwise.
186
 */
187
  public boolean apply(Effect effect, int position)
188
    {
189
    int num = effect.getType().ordinal();
190
    return mQueues[num].add(effect,position);
191
    }
192

  
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
/**
195
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
196
 */
197
  public void markForDeletion()
198
    {
199
    for( int i=0; i<EffectType.LENGTH; i++)
200
      {
201
      mQueues[i].markForDeletion();
202
      }
203
    }
204

  
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
/**
207
 * Return number of effects of the given type currently in the Queue.
208
 *
209
 * @param type The EffectType.
210
 * @return Number of effects of the given type currently in the Queue.
211
 */
212
  public int getNumEffects(EffectType type)
213
    {
214
    int num = type.ordinal();
215
    return mQueues[num].getNumEffects();
216
    }
217

  
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219
/**
220
 * Return a string describing all effects in the queues.
221
 */
222
  public String debug(int depth)
223
    {
224
    StringBuilder s = new StringBuilder();
225
    for(int i=0; i<depth; i++) s.append(" ");
226
    String space = s.toString();
227

  
228
    String mat = mQueues[0].retEffects();
229
    String ver = mQueues[1].retEffects();
230
    String fra = mQueues[2].retEffects();
231
    String pos = mQueues[3].retEffects();
232

  
233
    return space+"MAT: "+mat+"\n"+space+"VER: "+ver+"\n"+space+"FRA: "+fra+"\n"+space+"POS: "+pos;
234
    }
235
  }
src/main/java/org/distorted/library/main/DistortedFramebuffer.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library 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 GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.main;
22

  
23
import android.opengl.GLES30;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
/**
27
 * Class which represents a OpenGL Framebuffer object.
28
 * <p>
29
 * User is able to create offscreen FBOs and both a) render to them b) use their COLOR0 attachment as
30
 * an input texture. Attaching Depths and/or Stencils is also possible.
31
 */
32
public class DistortedFramebuffer extends InternalOutputSurface
33
  {
34

  
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36
// Must be called from a thread holding OpenGL Context
37

  
38
  public void create()
39
    {
40
    if( mNumFBOs==DistortedLibrary.WAIT_FOR_FBO_QUEUE_SIZE )
41
      {
42
      // only now we know how many FBOs there should be
43
      mNumFBOs = DistortedLibrary.getQueueSize();
44
      allocateColor();
45
      allocateStuffDependantOnNumFBOS();
46
      }
47

  
48
    //////////////////////////////////////////////////////////////
49
    // COLOR
50

  
51
    if( mColorCreated==NOT_CREATED_YET )
52
      {
53
      GLES30.glGenTextures( mNumFBOs*mNumColors, mColorH, 0);
54
      GLES30.glGenFramebuffers(mNumFBOs, mFBOH, 0);
55

  
56
      for(int i=0; i<mNumFBOs; i++)
57
        {
58
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i]);
59

  
60
        for(int j=0; j<mNumColors; j++)
61
          {
62
          GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[i*mNumColors+j]);
63
          GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
64
          GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);
65
          GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
66
          GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
67
          GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, mRealWidth, mRealHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null);
68
          }
69

  
70
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, mColorH[i*mNumColors], 0);
71
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
72
        }
73

  
74
      // TODO
75
      mColorCreated = checkStatus("color");
76
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
77
      }
78

  
79
    //////////////////////////////////////////////////////////////
80
    // DEPTH / STENCIL
81

  
82
    if( mDepthStencilCreated==NOT_CREATED_YET ) // we need to create a new DEPTH or STENCIL attachment
83
      {
84
      GLES30.glGenTextures(mNumFBOs, mDepthStencilH, 0);
85

  
86
      for(int i=0; i<mNumFBOs; i++)
87
        {
88
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mDepthStencilH[i]);
89
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
90
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);
91
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
92
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);
93

  
94
        if (mDepthStencil == DEPTH_NO_STENCIL)
95
          {
96
          GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH_COMPONENT, mRealWidth, mRealHeight, 0, GLES30.GL_DEPTH_COMPONENT, GLES30.GL_UNSIGNED_INT, null);
97
          }
98
        else if (mDepthStencil == BOTH_DEPTH_STENCIL)
99
          {
100
          GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH24_STENCIL8, mRealWidth, mRealHeight, 0, GLES30.GL_DEPTH_STENCIL, GLES30.GL_UNSIGNED_INT_24_8, null);
101
          }
102
        }
103
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
104

  
105
      for(int i=0; i<mNumFBOs; i++)
106
        {
107
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i]);
108

  
109
        if (mDepthStencil == DEPTH_NO_STENCIL)
110
          {
111
          GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, mDepthStencilH[i], 0);
112
          }
113
        else if (mDepthStencil == BOTH_DEPTH_STENCIL)
114
          {
115
          GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_STENCIL_ATTACHMENT, GLES30.GL_TEXTURE_2D, mDepthStencilH[i], 0);
116
          }
117
        }
118

  
119
      // TODO
120
      mDepthStencilCreated = checkStatus("depth");
121
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
122
      }
123

  
124
    //////////////////////////////////////////////////////////////
125
    // DETACH
126

  
127
    // TODO
128
    if( mDepthStencilCreated==DONT_CREATE && mDepthStencilH[0]>0 ) // we need to detach and recreate the DEPTH attachment.
129
      {
130
      // OpenGL ES 3.0.5 spec, chapter 4.4.2.4 :
131
      // "Note that the texture image is specifically not detached from any other framebuffer objects.
132
      //  Detaching the texture image from any other framebuffer objects is the responsibility of the application."
133

  
134
      for(int i=0; i<mNumFBOs; i++)
135
        {
136
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i]);
137
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, 0, 0);
138
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_STENCIL_ATTACHMENT, GLES30.GL_TEXTURE_2D, 0, 0);
139
        mDepthStencilH[i]=0;
140
        }
141

  
142
      GLES30.glDeleteTextures(mNumFBOs, mDepthStencilH, 0);
143
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
144
      }
145
    }
146

  
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
// TODO
149

  
150
  private int checkStatus(String message)
151
    {
152
    int status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);
153

  
154
    if(status != GLES30.GL_FRAMEBUFFER_COMPLETE)
155
      {
156
      DistortedLibrary.logMessage("DistortedFramebuffer: FRAMEBUFFER INCOMPLETE, "+message+" error="+status);
157

  
158
      GLES30.glDeleteTextures(1, mColorH, 0);
159
      GLES30.glDeleteTextures(1, mDepthStencilH, 0);
160
      GLES30.glDeleteFramebuffers(1, mFBOH, 0);
161
      mFBOH[0]= 0;
162

  
163
      return FAILED_TO_CREATE;
164
      }
165

  
166
    return CREATED;
167
    }
168

  
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170
// Must be called from a thread holding OpenGL Context
171

  
172
  public void delete()
173
    {
174
    if( mColorH[0]>0 )
175
      {
176
      GLES30.glDeleteTextures(mNumFBOs*mNumColors, mColorH, 0);
177
      mColorCreated = NOT_CREATED_YET;
178

  
179
      for(int i=0; i<mNumFBOs*mNumColors; i++) mColorH[i] = 0;
180
      }
181

  
182
    if( mDepthStencilH[0]>0 )
183
      {
184
      GLES30.glDeleteTextures(mNumFBOs, mDepthStencilH, 0);
185
      mDepthStencilCreated = NOT_CREATED_YET;
186

  
187
      for(int i=0; i<mNumFBOs; i++) mDepthStencilH[i] = 0;
188
      }
189

  
190
    if( mNumFBOs>0 && mFBOH[0]>0 )
191
      {
192
      GLES30.glDeleteFramebuffers(mNumFBOs, mFBOH, 0);
193
      }
194

  
195
    for(int i=0; i<mNumFBOs; i++)
196
      {
197
      mFBOH[i] = 0;
198
      }
199
    }
200

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
// called from onDestroy(); mark OpenGL assets as 'not created'
203

  
204
  public void recreate()
205
    {
206
    if( mColorCreated!=DONT_CREATE )
207
      {
208
      mColorCreated = NOT_CREATED_YET;
209
      mColorH[0] = 0;
210
      }
211
    if( mDepthStencilCreated!=DONT_CREATE )
212
      {
213
      mDepthStencilCreated = NOT_CREATED_YET;
214
      mDepthStencilH[0] = 0;
215
      }
216
    for(int i=0; i<mNumFBOs; i++)
217
      {
218
      mFBOH[i] = 0;
219
      }
220
    }
221

  
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

  
224
  boolean setAsInput(int fbo, int texture)
225
    {
226
    if( texture>=0 && texture<mNumColors && fbo>=0 && fbo<mNumFBOs && mColorH[mNumColors*fbo + texture]>0 )
227
      {
228
      GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
229
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[mNumColors*fbo + texture]);
230
      return true;
231
      }
232

  
233
    return false;
234
    }
235

  
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// create a multi-framebuffer (1 object containing multiple FBOs)
238

  
239
  DistortedFramebuffer(int numfbos, int numcolors, int depthStencil, int type, int storage, int width, int height)
240
    {
241
    super(width,height,NOT_CREATED_YET,numfbos,numcolors,depthStencil,NOT_CREATED_YET, type, storage);
242
    markForCreation();
243
    }
244

  
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246
// create SYSTEM or TREE framebuffers (those are just like normal FBOs, just hold information
247
// that they were autocreated only for the Library's internal purposes (SYSTEM) or for using
248
// inside a Tree of DistortedNodes (TREE)
249
// SYSTEM surfaces do not get removed in onDestroy().
250

  
251
  DistortedFramebuffer(int numcolors, int depthStencil, int type, int width, int height)
252
    {
253
    this(1,numcolors,depthStencil,type,STORAGE_PRIVATE,width,height);
254
    }
255

  
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
// PUBLIC API
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259
/**
260
 * Create new offscreen Framebuffer with configurable number of COLOR, DEPTH and STENCIL attachments.
261
 *
262
 * @param width        Width of all the COLOR attachments.
263
 * @param height       Height of all the COLOR attachments.
264
 * @param numcolors    How many COLOR attachments to create?
265
 * @param depthStencil Add DEPTH or STENCIL attachment?
266
 *                     Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
267
 */
268
  @SuppressWarnings("unused")
269
  public DistortedFramebuffer(int width, int height, int numcolors, int depthStencil)
270
    {
271
    this(1,numcolors,depthStencil,TYPE_USER,STORAGE_PRIVATE,width,height);
272
    }
273

  
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
/**
276
 * Bind the underlying rectangle of pixels as a OpenGL Texture.
277
 *
278
 * @param texture The Texture number to bind (and thus read from).
279
 * @return <code>true</code> if successful.
280
 */
281
  public boolean setAsInput(int texture)
282
    {
283
    if( texture>=0 && texture<mNumColors && mColorH[texture]>0 )
284
      {
285
      GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
286
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[2*mCurrFBO+texture]);
287
      return true;
288
      }
289

  
290
    return false;
291
    }
292

  
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294
  /**
295
   * Attach the texture'th Texture to COLOR0 attachment.
296
   *
297
   * @param texture The Texture number to attach (and subsequently use to render to)
298
   */
299
  public void bindForOutput(int texture)
300
    {
301
    if( texture>=0 && texture<mNumColors && mColorH[texture]>0 )
302
      {
303
      GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, mColorH[2*mCurrFBO+texture], 0);
304
      }
305
    }
306

  
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308
/**
309
 * Enable.disable DEPTH and STENCIL buffers.
310
 *
311
 * @param depthStencil Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
312
 */
313
  public void enableDepthStencil(int depthStencil)
314
    {
315
    if( depthStencil != mDepthStencil )
316
      {
317
      mDepthStencil = depthStencil;
318

  
319
      if( depthStencil!= NO_DEPTH_NO_STENCIL && mDepthStencilCreated==DONT_CREATE )
320
        {
321
        mDepthStencilCreated = NOT_CREATED_YET;
322
        markForCreation();
323
        }
324
      if( depthStencil== NO_DEPTH_NO_STENCIL && mDepthStencilCreated!=DONT_CREATE )
325
        {
326
        mDepthStencilCreated = DONT_CREATE;
327
        markForCreation();
328
        }
329
      }
330
    }
331

  
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333
/**
334
 * Return the ID of the Texture (COLOR attachment 0) that's backing this FBO.
335
 * <p>
336
 * Catch: this will only work if the library has had time to actually create the texture. Remember
337
 * that the texture gets created only on first render, thus creating a Texture object and immediately
338
 * calling this method will return an invalid (negative) result.
339
 *
340
 * @return If there was not a single render between creation of the Object and calling this method on
341
 *         it, return a negative value. Otherwise, return ID of COLOR attachment 0.
342
 */
343
  public int getTextureID()
344
    {
345
    return mColorH[0];
346
    }
347

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349
/**
350
 * Bind one of the underlying FBOs to GL_READ_FRAMEBUFFER.
351
 * Useful for a subsequent glReadBuffer / glReadPixels.
352
 *
353
 * @param fbo which of the underlying FBOs to bind.
354
 * @return <code>true</code> if successful.
355
 */
356
  public boolean setAsReadFramebuffer(int fbo)
357
    {
358
    if( fbo>=0 && fbo<mNumFBOs )
359
      {
360
      GLES30.glBindFramebuffer(GLES30.GL_READ_FRAMEBUFFER, mFBOH[fbo]);
361
      return true;
362
      }
363

  
364
    return false;
365
    }
366
  }
src/main/java/org/distorted/library/main/DistortedFramebuffer.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library 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 GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.main;
22

  
23
import android.opengl.GLES30;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
/**
27
 * Class which represents a OpenGL Framebuffer object.
28
 * <p>
29
 * User is able to create offscreen FBOs and both a) render to them b) use their COLOR0 attachment as
30
 * an input texture. Attaching Depths and/or Stencils is also possible.
31
 */
32
public class DistortedFramebuffer extends InternalOutputSurface
33
  {
34

  
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36
// Must be called from a thread holding OpenGL Context
37

  
38
  public void create()
39
    {
40
    if( mNumFBOs==DistortedLibrary.WAIT_FOR_FBO_QUEUE_SIZE )
41
      {
42
      // only now we know how many FBOs there should be
43
      mNumFBOs = DistortedLibrary.getQueueSize();
44
      allocateColor();
45
      allocateStuffDependantOnNumFBOS();
46
      }
47

  
48
    //////////////////////////////////////////////////////////////
49
    // COLOR
50

  
51
    if( mColorCreated==NOT_CREATED_YET )
52
      {
53
      GLES30.glGenTextures( mNumFBOs*mNumColors, mColorH, 0);
54
      GLES30.glGenFramebuffers(mNumFBOs, mFBOH, 0);
55

  
56
      for(int i=0; i<mNumFBOs; i++)
57
        {
58
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i]);
59

  
60
        for(int j=0; j<mNumColors; j++)
61
          {
62
          GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[i*mNumColors+j]);
63
          GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
64
          GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);
65
          GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
66
          GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
67
          GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, mRealWidth, mRealHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null);
68
          }
69

  
70
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, mColorH[i*mNumColors], 0);
71
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
72
        }
73

  
74
      // TODO
75
      mColorCreated = checkStatus("color");
76
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
77
      }
78

  
79
    //////////////////////////////////////////////////////////////
80
    // DEPTH / STENCIL
81

  
82
    if( mDepthStencilCreated==NOT_CREATED_YET ) // we need to create a new DEPTH or STENCIL attachment
83
      {
84
      GLES30.glGenTextures(mNumFBOs, mDepthStencilH, 0);
85

  
86
      for(int i=0; i<mNumFBOs; i++)
87
        {
88
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mDepthStencilH[i]);
89
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
90
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);
91
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
92
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);
93

  
94
        if (mDepthStencil == DEPTH_NO_STENCIL)
95
          {
96
          GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH_COMPONENT, mRealWidth, mRealHeight, 0, GLES30.GL_DEPTH_COMPONENT, GLES30.GL_UNSIGNED_INT, null);
97
          }
98
        else if (mDepthStencil == BOTH_DEPTH_STENCIL)
99
          {
100
          GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH24_STENCIL8, mRealWidth, mRealHeight, 0, GLES30.GL_DEPTH_STENCIL, GLES30.GL_UNSIGNED_INT_24_8, null);
101
          }
102
        }
103
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
104

  
105
      for(int i=0; i<mNumFBOs; i++)
106
        {
107
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i]);
108

  
109
        if (mDepthStencil == DEPTH_NO_STENCIL)
110
          {
111
          GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, mDepthStencilH[i], 0);
112
          }
113
        else if (mDepthStencil == BOTH_DEPTH_STENCIL)
114
          {
115
          GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_STENCIL_ATTACHMENT, GLES30.GL_TEXTURE_2D, mDepthStencilH[i], 0);
116
          }
117
        }
118

  
119
      // TODO
120
      mDepthStencilCreated = checkStatus("depth");
121
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
122
      }
123

  
124
    //////////////////////////////////////////////////////////////
125
    // DETACH
126

  
127
    // TODO
128
    if( mDepthStencilCreated==DONT_CREATE && mDepthStencilH[0]>0 ) // we need to detach and recreate the DEPTH attachment.
129
      {
130
      // OpenGL ES 3.0.5 spec, chapter 4.4.2.4 :
131
      // "Note that the texture image is specifically not detached from any other framebuffer objects.
132
      //  Detaching the texture image from any other framebuffer objects is the responsibility of the application."
133

  
134
      for(int i=0; i<mNumFBOs; i++)
135
        {
136
        GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i]);
137
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, 0, 0);
138
        GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_STENCIL_ATTACHMENT, GLES30.GL_TEXTURE_2D, 0, 0);
139
        mDepthStencilH[i]=0;
140
        }
141

  
142
      GLES30.glDeleteTextures(mNumFBOs, mDepthStencilH, 0);
143
      GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
144
      }
145
    }
146

  
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
// TODO
149

  
150
  private int checkStatus(String message)
151
    {
152
    int status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);
153

  
154
    if(status != GLES30.GL_FRAMEBUFFER_COMPLETE)
155
      {
156
      DistortedLibrary.logMessage("DistortedFramebuffer: FRAMEBUFFER INCOMPLETE, "+message+" error="+status);
157

  
158
      GLES30.glDeleteTextures(1, mColorH, 0);
159
      GLES30.glDeleteTextures(1, mDepthStencilH, 0);
160
      GLES30.glDeleteFramebuffers(1, mFBOH, 0);
161
      mFBOH[0]= 0;
162

  
163
      return FAILED_TO_CREATE;
164
      }
165

  
166
    return CREATED;
167
    }
168

  
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170
// Must be called from a thread holding OpenGL Context
171

  
172
  public void delete()
173
    {
174
    if( mColorH[0]>0 )
175
      {
176
      GLES30.glDeleteTextures(mNumFBOs*mNumColors, mColorH, 0);
177
      mColorCreated = NOT_CREATED_YET;
178

  
179
      for(int i=0; i<mNumFBOs*mNumColors; i++) mColorH[i] = 0;
180
      }
181

  
182
    if( mDepthStencilH[0]>0 )
183
      {
184
      GLES30.glDeleteTextures(mNumFBOs, mDepthStencilH, 0);
185
      mDepthStencilCreated = NOT_CREATED_YET;
186

  
187
      for(int i=0; i<mNumFBOs; i++) mDepthStencilH[i] = 0;
188
      }
189

  
190
    if( mNumFBOs>0 && mFBOH[0]>0 )
191
      {
192
      GLES30.glDeleteFramebuffers(mNumFBOs, mFBOH, 0);
193
      }
194

  
195
    for(int i=0; i<mNumFBOs; i++)
196
      {
197
      mFBOH[i] = 0;
198
      }
199
    }
200

  
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
// called from onDestroy(); mark OpenGL assets as 'not created'
203

  
204
  public void recreate()
205
    {
206
    if( mColorCreated!=DONT_CREATE )
207
      {
208
      mColorCreated = NOT_CREATED_YET;
209
      mColorH[0] = 0;
210
      }
211
    if( mDepthStencilCreated!=DONT_CREATE )
212
      {
213
      mDepthStencilCreated = NOT_CREATED_YET;
214
      mDepthStencilH[0] = 0;
215
      }
216
    for(int i=0; i<mNumFBOs; i++)
217
      {
218
      mFBOH[i] = 0;
219
      }
220
    }
221

  
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

  
224
  boolean setAsInput(int fbo, int texture)
225
    {
226
    if( texture>=0 && texture<mNumColors && fbo>=0 && fbo<mNumFBOs && mColorH[mNumColors*fbo + texture]>0 )
227
      {
228
      GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
229
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[mNumColors*fbo + texture]);
230
      return true;
231
      }
232

  
233
    return false;
234
    }
235

  
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// create a multi-framebuffer (1 object containing multiple FBOs)
238

  
239
  DistortedFramebuffer(int numfbos, int numcolors, int depthStencil, int type, int storage, int width, int height)
240
    {
241
    super(width,height,NOT_CREATED_YET,numfbos,numcolors,depthStencil,NOT_CREATED_YET, type, storage);
242
    markForCreation();
243
    }
244

  
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246
// create SYSTEM or TREE framebuffers (those are just like normal FBOs, just hold information
247
// that they were autocreated only for the Library's internal purposes (SYSTEM) or for using
248
// inside a Tree of DistortedNodes (TREE)
249
// SYSTEM surfaces do not get removed in onDestroy().
250

  
251
  DistortedFramebuffer(int numcolors, int depthStencil, int type, int width, int height)
252
    {
253
    this(1,numcolors,depthStencil,type,STORAGE_PRIVATE,width,height);
254
    }
255

  
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
// PUBLIC API
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259
/**
260
 * Create new offscreen Framebuffer with configurable number of COLOR, DEPTH and STENCIL attachments.
261
 *
262
 * @param width        Width of all the COLOR attachments.
263
 * @param height       Height of all the COLOR attachments.
264
 * @param numcolors    How many COLOR attachments to create?
265
 * @param depthStencil Add DEPTH or STENCIL attachment?
266
 *                     Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
267
 */
268
  @SuppressWarnings("unused")
269
  public DistortedFramebuffer(int width, int height, int numcolors, int depthStencil)
270
    {
271
    this(1,numcolors,depthStencil,TYPE_USER,STORAGE_PRIVATE,width,height);
272
    }
273

  
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
/**
276
 * Bind the underlying rectangle of pixels as a OpenGL Texture.
277
 *
278
 * @param texture The Texture number to bind (and thus read from).
279
 * @return <code>true</code> if successful.
280
 */
281
  public boolean setAsInput(int texture)
282
    {
283
    if( texture>=0 && texture<mNumColors && mColorH[texture]>0 )
284
      {
285
      GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
286
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH[2*mCurrFBO+texture]);
287
      return true;
288
      }
289

  
290
    return false;
291
    }
292

  
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294
  /**
295
   * Attach the texture'th Texture to COLOR0 attachment.
296
   *
297
   * @param texture The Texture number to attach (and subsequently use to render to)
298
   */
299
  public void bindForOutput(int texture)
300
    {
301
    if( texture>=0 && texture<mNumColors && mColorH[texture]>0 )
302
      {
303
      GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, mColorH[2*mCurrFBO+texture], 0);
304
      }
305
    }
306

  
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308
/**
309
 * Enable.disable DEPTH and STENCIL buffers.
310
 *
311
 * @param depthStencil Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
312
 */
313
  public void enableDepthStencil(int depthStencil)
314
    {
315
    if( depthStencil != mDepthStencil )
316
      {
317
      mDepthStencil = depthStencil;
318

  
319
      if( depthStencil!= NO_DEPTH_NO_STENCIL && mDepthStencilCreated==DONT_CREATE )
320
        {
321
        mDepthStencilCreated = NOT_CREATED_YET;
322
        markForCreation();
323
        }
324
      if( depthStencil== NO_DEPTH_NO_STENCIL && mDepthStencilCreated!=DONT_CREATE )
325
        {
326
        mDepthStencilCreated = DONT_CREATE;
327
        markForCreation();
328
        }
329
      }
330
    }
331

  
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333
/**
334
 * Return the ID of the Texture (COLOR attachment 0) that's backing this FBO.
335
 * <p>
336
 * Catch: this will only work if the library has had time to actually create the texture. Remember
337
 * that the texture gets created only on first render, thus creating a Texture object and immediately
338
 * calling this method will return an invalid (negative) result.
339
 *
340
 * @return If there was not a single render between creation of the Object and calling this method on
341
 *         it, return a negative value. Otherwise, return ID of COLOR attachment 0.
342
 */
343
  public int getTextureID()
344
    {
345
    return mColorH[0];
346
    }
347

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349
/**
350
 * Bind one of the underlying FBOs to GL_READ_FRAMEBUFFER.
351
 * Useful for a subsequent glReadBuffer / glReadPixels.
352
 *
353
 * @param fbo which of the underlying FBOs to bind.
354
 * @return <code>true</code> if successful.
355
 */
356
  public boolean setAsReadFramebuffer(int fbo)
357
    {
358
    if( fbo>=0 && fbo<mNumFBOs )
359
      {
360
      GLES30.glBindFramebuffer(GLES30.GL_READ_FRAMEBUFFER, mFBOH[fbo]);
361
      return true;
362
      }
363

  
364
    return false;
365
    }
366
  }
src/main/java/org/distorted/library/main/DistortedLibrary.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library 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 GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.main;
22

  
23
import android.opengl.GLES30;
24
import android.opengl.GLES31;
25

  
26
import java.io.InputStream;
27
import java.nio.ByteBuffer;
28
import java.nio.ByteOrder;
29
import java.nio.FloatBuffer;
30
import java.nio.IntBuffer;
31
import java.util.regex.Matcher;
32
import java.util.regex.Pattern;
33

  
34
import org.distorted.library.R;
35
import org.distorted.library.effect.Effect;
36
import org.distorted.library.effectqueue.EffectQueue;
37
import org.distorted.library.effectqueue.EffectQueuePostprocess;
38
import org.distorted.library.effect.EffectType;
39
import org.distorted.library.effect.FragmentEffect;
40
import org.distorted.library.effect.PostprocessEffect;
41
import org.distorted.library.effect.VertexEffect;
42
import org.distorted.library.effectqueue.EffectQueueVertex;
43
import org.distorted.library.mesh.DeferredJobs;
44
import org.distorted.library.mesh.MeshBase;
45
import org.distorted.library.message.EffectMessageSender;
46
import org.distorted.library.program.DistortedProgram;
47
import org.distorted.library.program.VertexCompilationException;
48
import org.distorted.library.type.Dynamic;
49

  
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
/**
52
 * A singleton class used to control various global dialog_settings.
53
 */
54
public class DistortedLibrary
55
  {
56
  /**
57
   * When creating an instance of a DistortedTexture from another instance, clone the Bitmap that's
58
   * backing up our DistortedTexture.
59
   * <p>
60
   * This way we can have two DistortedTextures, both backed up by the same Bitmap, to which we can
61
   * apply different effects. Used in the copy constructor.
62
   */
63
  public static final int CLONE_SURFACE = 0x1;
64
  /**
65
   * When creating an instance of a DistortedEffects from another instance, clone the Matrix Effects.
66
   * <p>
67
   * This way we can have two different DistortedEffects sharing the MATRIX queue.
68
   */
69
  public static final int CLONE_MATRIX = 0x2;
70
  /**
71
   * When creating an instance of a DistortedEffects from another instance, clone the Vertex Effects.
72
   * <p>
73
   * This way we can have two different DistortedEffects sharing the VERTEX queue.
74
   */
75
  public static final int CLONE_VERTEX  = 0x4;
76
  /**
77
   * When creating an instance of a DistortedEffects from another instance, clone the Fragment Effects.
78
   * <p>
79
   * This way we can have two different DistortedEffects sharing the FRAGMENT queue.
80
   */
81
  public static final int CLONE_FRAGMENT= 0x8;
82
   /**
83
   * When creating an instance of a DistortedEffects from another instance, clone the PostProcess Effects.
84
   * <p>
85
   * This way we can have two different DistortedEffects sharing the POSTPROCESS queue.
86
   */
87
  public static final int CLONE_POSTPROCESS= 0x10;
88
  /**
89
   * When creating an instance of a DistortedNode from another instance, clone the children Nodes.
90
   * <p>
91
   * This is mainly useful for creating many similar sub-trees and rendering then at different places
92
   * on the screen with (optionally) different Effects.
93
   */
94
  public static final int CLONE_CHILDREN= 0x20;
95

  
96
  /**
97
   * When creating a DistortedScreen (which needs to have mFBOQueueSize FBOs attached), pass this
98
   * constant for 'numOfFBOs' and the number of backing FBOs will be taken from 'mFBOQueueSize'
99
   * (the value of which is most likely unknown at the time of creation of the Screen)
100
   */
101
  public static final int WAIT_FOR_FBO_QUEUE_SIZE = -1;
102
  /**
103
   * Work around bugs in ARM Mali driver by, instead to a single FBO, rendering to a circular queue
104
   * of mFBOQueueSize FBOs. (otherwise we sometimes get a 'full pipeline flush' and the end result
105
   * might be missing part of the Objects)
106
   * <p>
107
   * This bug only exists on Mali driver r12. (or more precisely it's there in r12 but fixed in r22)
108
   * <p>
109
   * <a href="https://community.arm.com/graphics/f/discussions/10285/opengl-es-3-1-on-mali-t880-flashes">...</a>
110
   */
111
  private static int mFBOQueueSize;
112
  private static int mGLSL;
113
  private static String mGLSL_VERSION;
114
  private static boolean mOITCompilationAttempted, mNeedsTransformFeedback;
115

  
116
  private static int mMaxTextureSize         = Integer.MAX_VALUE;
117
  private static int mMaxNumberOfVerUniforms = Integer.MAX_VALUE;
118
  private static int mMaxNumberOfFraUniforms = Integer.MAX_VALUE;
119

  
120
  private static boolean mBuggyUBOs;
121
  private static String mVendor, mVersion, mRenderer;
122
  private static boolean mFastCompilationTF;
123

  
124
  //////////////////////////////////////////////////////////////////////////////////////////////
125
  /// MAIN PROGRAM ///
126
  private static DistortedProgram mMainProgram;
127
  private static int mMainTextureH;
128
  private static int mTransformFeedbackH;
129

  
130
  /// NORMAL PROGRAM /////
131
  private static DistortedProgram mNormalProgram;
132
  private static int mNormalProjectionH;
133

  
134
  /// MAIN OIT PROGRAM ///
135
  private static DistortedProgram mMainOITProgram;
136
  private static int mMainOITTextureH;
137
  private static int mMainOITSizeH;
138
  private static int mMainOITNumRecordsH;
139

  
140
  /// BLIT PROGRAM ///
141
  private static DistortedProgram mBlitProgram;
142
  private static int mBlitTextureH;
143
  private static int mBlitDepthH;
144
  private static final FloatBuffer mQuadPositions;
145

  
146
  /// FULL PROGRAM ///
147
  private static DistortedProgram mFullProgram;
148

  
149
  static
150
    {
151
    float[] positionData= { -0.5f, -0.5f,  -0.5f, 0.5f,  0.5f,-0.5f,  0.5f, 0.5f };
152
    mQuadPositions = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder()).asFloatBuffer();
153
    mQuadPositions.put(positionData).position(0);
154
    }
155

  
156
  /// BLIT DEPTH PROGRAM ///
157
  private static DistortedProgram mBlitDepthProgram;
158
  private static int mBlitDepthTextureH;
159
  private static int mBlitDepthDepthTextureH;
160
  private static int mBlitDepthTexCorrH;
161

  
162
  /// Program Handles ///
163
  private static int mMainProgramH, mFullProgramH, mMainOITProgramH;
164

  
165
  /// OIT SSBO BUFFER ///
166
  private static final int[] mLinkedListSSBO = new int[1];
167
  private static int[] mAtomicCounter;
168
  private static int   mCurrBuffer;
169

  
170
  static
171
    {
172
    mLinkedListSSBO[0]= -1;
173
    mCurrBuffer       =  0;
174
    }
175

  
176
  ///////////////////////////////////////////////////////////////
177
  // meaning: allocate 1.0 screenful of places for transparent
178
  // fragments in the SSBO backing up the OIT render method.
179
  private static float mBufferSize=1.0f;
180

  
181
  /// OIT CLEAR PROGRAM ///
182
  private static DistortedProgram mOITClearProgram;
183
  private static int mOITClearDepthH;
184
  private static int mOITClearTexCorrH;
185
  private static int mOITClearSizeH;
186

  
187
  /// OIT BUILD PROGRAM ///
188
  private static DistortedProgram mOITBuildProgram;
189
  private static int mOITBuildTextureH;
190
  private static int mOITBuildDepthTextureH;
191
  private static int mOITBuildDepthH;
192
  private static int mOITBuildTexCorrH;
193
  private static int mOITBuildSizeH;
194
  private static int mOITBuildNumRecordsH;
195

  
196
  /// OIT COLLAPSE PROGRAM ///
197
  private static DistortedProgram mOITCollapseProgram;
198
  private static int mOITCollapseDepthTextureH;
199
  private static int mOITCollapseDepthH;
200
  private static int mOITCollapseTexCorrH;
201
  private static int mOITCollapseSizeH;
202

  
203
  /// OIT RENDER PROGRAM ///
204
  private static DistortedProgram mOITRenderProgram;
205
  private static int mOITRenderDepthH;
206
  private static int mOITRenderTexCorrH;
207
  private static int mOITRenderSizeH;
208

  
209
  /// END PROGRAMS //////
210

  
211
  /**
212
   * Every application using the library must implement this interface so that the library can send
213
   * it exceptions that arise. The exceptions may come at any time, for example the library will
214
   * compile its OIT problem only on the first attempt to use the OIT
215
   * Those will mainly be hardware-related: shaders do not compile on particular hardware, the required
216
   * OpenGL ES 3.0 is not supported, etc.
217
   * <p>
218
   * Additionally, the User must be able to provide version of the OpenGL supported by the underlying
219
   * hardware and InputStreams to given local files.
220
   */
221
  public interface LibraryUser
222
    {
223
    void distortedException(Exception ex);
224
    InputStream localFile(int fileID);
225
    void logMessage(String message);
226
    }
227

  
228
  private static LibraryUser mUser;
229

  
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231
// private: hide this from Javadoc
232

  
233
  private DistortedLibrary()
234
    {
235

  
236
    }
237

  
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

  
240
  private static void createMainProgram()
241
    {
242
    // MAIN PROGRAM ////////////////////////////////////
243
    final InputStream mainVertStream = mUser.localFile(R.raw.main_vertex_shader);
244
    final InputStream mainFragStream = mUser.localFile(R.raw.main_fragment_shader);
245

  
246
    int numF = FragmentEffect.getNumEnabled();
247
    int numV = VertexEffect.getNumEnabled();
248

  
249
    String mainVertHeader= mGLSL_VERSION + ("#define NUM_VERTEX "   + ( numV>0 ? getMax(EffectType.VERTEX  ) : 0 ) + "\n");
250
    String mainFragHeader= mGLSL_VERSION + ("#define NUM_FRAGMENT " + ( numF>0 ? getMax(EffectType.FRAGMENT) : 0 ) + "\n");
251

  
252
    mainVertHeader += "#define MAX_COMPON " + MeshBase.getMaxEffComponents() + "\n";
253
    if( MeshBase.getUseCenters() ) mainVertHeader += "#define COMP_CENTERS\n";
254
    if( mBuggyUBOs )               mainVertHeader += "#define BUGGY_UBOS\n";
255

  
256
    String enabledEffectV= VertexEffect.getGLSL();
257
    String enabledEffectF= FragmentEffect.getGLSL();
258

  
259
    String[] feedback = { "v_Position", "v_endPosition" };
260

  
261
    try
262
      {
263
      mMainProgram = new DistortedProgram(mainVertStream, mainFragStream, mainVertHeader,
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff