Project

General

Profile

« Previous | Next » 

Revision d236a443

Added by Leszek Koltunski 5 days ago

transition the second half of the 'main' package to Kotlin. Compiles, but fails to run.

View differences:

src/main/java/org/distorted/library/effect/PostprocessEffectBlur.kt
41 41

  
42 42
        ///////////////////////////////////////////////////////////////////////////////////////////////////
43 43
        // Clean up of static variables on exit. Called by reflection from super class.
44
        @Suppress("unused") fun destroyStatics() = PostprocessEffectBlurred.destroyStatics()
44
        @Suppress("unused")
45
        @JvmStatic
46
        fun destroyStatics() = PostprocessEffectBlurred.destroyStatics()
45 47
    }
46 48

  
47 49
    ///////////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/effect/PostprocessEffectBlurred.kt
206 206
        private var mIndex2 = 0
207 207

  
208 208
        ///////////////////////////////////////////////////////////////////////////////////////////////////
209
        fun destroyStatics()
209
        @JvmStatic fun destroyStatics()
210 210
        {
211 211
            mProgram1 = null
212 212
            mProgram2 = null
......
221 221
        /**
222 222
         * Have to call this before the shaders get compiled (i.e before DistortedLibrary.onCreate()) for the Effect to work.
223 223
         */
224
        fun enable(prog1: String, prog2: String)
224
        @JvmStatic fun enable(prog1: String, prog2: String)
225 225
        {
226 226
            val vertex =
227 227
                """ precision lowp float;     
src/main/java/org/distorted/library/effect/PostprocessEffectBorder.kt
39 39
    {
40 40
        ///////////////////////////////////////////////////////////////////////////////////////////
41 41
        // Clean up of static variables on exit. Called by reflection from super class.
42
        @Suppress("unused") fun destroyStatics() { }
43

  
44
        ///////////////////////////////////////////////////////////////////////////////////////////
45
        // PUBLIC API
46
        ///////////////////////////////////////////////////////////////////////////////////////////
42
        @Suppress("unused") @JvmStatic fun destroyStatics() { }
47 43
        /**
48 44
         * No local programs; we do not postprocess anything here. No need to do anything
49 45
         */
src/main/java/org/distorted/library/effect/PostprocessEffectGlow.kt
35 35

  
36 36
    companion object
37 37
    {
38
        ///////////////////////////////////////////////////////////////////////////////////////////////////
39
        // PUBLIC API
40
        ///////////////////////////////////////////////////////////////////////////////////////////////////
41 38
        /**
42 39
         * Have to call this before the shaders get compiled (i.e before DistortedLibrary.onCreate()) for the Effect to work.
43 40
         */
......
45 42

  
46 43
        ///////////////////////////////////////////////////////////////////////////////////////////////////
47 44
        // Clean up of static variables on exit. Called by reflection from super class.
48
        @Suppress("unused")
49
        fun destroyStatics() = PostprocessEffectBlurred.destroyStatics()
45
        @Suppress("unused") @JvmStatic fun destroyStatics() = PostprocessEffectBlurred.destroyStatics()
50 46
    }
51 47
    ///////////////////////////////////////////////////////////////////////////////////////////////////
52 48
    override fun compute(uniforms: FloatArray, index: Int, currentDuration: Long, step: Long): Boolean
src/main/java/org/distorted/library/effectqueue/EffectQueue.kt
65 65

  
66 66
        ///////////////////////////////////////////////////////////////////////////////////////////
67 67
        @JvmStatic
68
        fun createQueues() : Array<EffectQueue?>
68
        fun createQueues() : Array<EffectQueue>
69 69
        {
70 70
            val queues: Array<EffectQueue?> = arrayOfNulls(EffectType.LENGTH)
71 71

  
......
74 74
            queues[2] = EffectQueueFragment()
75 75
            queues[3] = EffectQueuePostprocess()
76 76

  
77
            return queues
77
            return queues.requireNoNulls()
78 78
        }
79 79

  
80 80
        ///////////////////////////////////////////////////////////////////////////////////////////
81 81
        @JvmStatic
82
        fun createQueues(from: Array<EffectQueue?>, flags: Int) : Array<EffectQueue?>
82
        fun createQueues(from: Array<EffectQueue>, flags: Int) : Array<EffectQueue>
83 83
        {
84 84
            val queues: Array<EffectQueue?> = arrayOfNulls(EffectType.LENGTH)
85 85

  
......
88 88
            queues[2] = if ((flags and DistortedLibrary.CLONE_FRAGMENT   ) != 0) from[2] else EffectQueueFragment()
89 89
            queues[3] = if ((flags and DistortedLibrary.CLONE_POSTPROCESS) != 0) from[3] else EffectQueuePostprocess()
90 90

  
91
            return queues
91
            return queues.requireNoNulls()
92 92
        }
93 93

  
94 94
        ///////////////////////////////////////////////////////////////////////////////////////////
src/main/java/org/distorted/library/effectqueue/EffectQueuePostprocess.kt
78 78

  
79 79
            mainVertHeader += "#define MAX_COMPON " + MeshBase.maxEffComponents + "\n"
80 80
            if (MeshBase.useCenters) mainVertHeader += "#define COMP_CENTERS\n"
81
            if (DistortedLibrary.isUBOBuggy()) mainVertHeader += "#define BUGGY_UBOS\n"
81
            if (DistortedLibrary.isUBOBuggy) mainVertHeader += "#define BUGGY_UBOS\n"
82 82
            mainVertHeader += "#define POSTPROCESS\n"
83 83

  
84 84
            val enabledEffectV = VertexEffect.getGLSL()
......
159 159
    fun preprocess(buffer: InternalOutputSurface, node: DistortedNode, distance: Float,
160 160
                   mipmap: Float, projection: FloatArray): Int
161 161
    {
162
        val mesh    = node.mesh
163
        val effects = node.effects
162
        val mesh    = node.mMesh
163
        val effects = node.mEffects
164 164
        val width   = buffer.mWidth
165 165
        val height  = buffer.mHeight
166 166

  
src/main/java/org/distorted/library/main/DistortedEffects.kt
17 17
// License along with this library; if not, write to the Free Software                           //
18 18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19 19
///////////////////////////////////////////////////////////////////////////////////////////////////
20
package org.distorted.library.main
20 21

  
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;
22
import org.distorted.library.effect.Effect
23
import org.distorted.library.effect.EffectName
24
import org.distorted.library.effect.EffectType
25
import org.distorted.library.effectqueue.EffectQueue
26
import org.distorted.library.effectqueue.EffectQueue.Companion.createQueues
27
import org.distorted.library.main.InternalStackFrameList.nextEffectsID
27 28

  
28 29
///////////////////////////////////////////////////////////////////////////////////////////////////
29 30
/**
30 31
 * Class containing Matrix, Vertex, Fragment and Postprocessing effect queues.
31
 * <p>
32
 *
32 33
 * The queues hold actual effects to be applied to a given (InputSurface,MeshBase) combo.
33 34
 */
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()
35
class DistortedEffects
36
{
37
    /**
38
     * Returns unique ID of this instance.
39
     *
40
     * @return ID of the object.
41
     */
42
    val iD: Long
43
    val queues: Array<EffectQueue>
44

  
45
    ///////////////////////////////////////////////////////////////////////////////////////////////////
46
    // PUBLIC API
47
    ///////////////////////////////////////////////////////////////////////////////////////////////////
48
    /**
49
     * Create empty effect queue.
50
     */
51
    constructor()
44 52
    {
45
    return mQueues;
53
        iD = nextEffectsID
54
        queues = createQueues()
46 55
    }
47 56

  
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49
// PUBLIC API
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
/**
52
 * Create empty effect queue.
53
 */
54
 public DistortedEffects()
57
    ///////////////////////////////////////////////////////////////////////////////////////////////////
58
    /**
59
     * Copy constructor.
60
     *
61
     * Whatever we do not clone gets created just like in the default constructor.
62
     *
63
     * @param dc    Source object to create our object from
64
     * @param flags A bitmask of values specifying what to copy.
65
     * For example, CLONE_VERTEX | CLONE_MATRIX.
66
     */
67
    constructor(dc: DistortedEffects, flags: Int)
55 68
    {
56
    mID = InternalStackFrameList.getNextEffectsID();
57
    mQueues = EffectQueue.createQueues();
69
        iD = nextEffectsID
70
        queues = createQueues(dc.queues, flags)
58 71
    }
59 72

  
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)
73
    ///////////////////////////////////////////////////////////////////////////////////////////////////
74
    /**
75
     * Return if this queue contains effect with a given ID.
76
     */
77
    fun exists(id: Long): Boolean
71 78
    {
72
    mID = InternalStackFrameList.getNextEffectsID();
73
    mQueues = EffectQueue.createQueues(dc.getQueues(),flags);
79
        val num = (id and EffectType.MASK.toLong()).toInt()
80
        return queues[num].exists(id)
74 81
    }
75 82

  
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)
83
    ///////////////////////////////////////////////////////////////////////////////////////////////////
84
    /**
85
     * Aborts all Effects.
86
     * @return Number of effects aborted.
87
     */
88
    fun abortAllEffects(): Int
92 89
    {
93
    int num = (int)(id&EffectType.MASK);
94
    return mQueues[num].exists(id);
95
    }
90
        var aborted = 0
96 91

  
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
      }
92
        for (i in 0 until EffectType.LENGTH)
93
        {
94
            aborted += queues[i].removeAll(true)
95
        }
110 96

  
111
    return aborted;
97
        return aborted
112 98
    }
113 99

  
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)
100
    ///////////////////////////////////////////////////////////////////////////////////////////////////
101
    /**
102
     * Aborts all Effects of a given type, for example all MATRIX Effects.
103
     *
104
     * @param type one of the constants defined in [EffectType]
105
     * @return Number of effects aborted.
106
     */
107
    fun abortByType(type: EffectType): Int
122 108
    {
123
    int num = type.ordinal();
124
    return mQueues[num].removeAll(true);
109
        val num = type.ordinal
110
        return queues[num].removeAll(true)
125 111
    }
126 112

  
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)
113
    ///////////////////////////////////////////////////////////////////////////////////////////////////
114
    /**
115
     * Aborts an Effect by its ID.
116
     *
117
     * @param id the Id of the Effect to be removed, as returned by getID().
118
     * @return Number of effects aborted.
119
     */
120
    fun abortById(id: Long): Int
135 121
    {
136
    int num = (int)(id&EffectType.MASK);
137
    return mQueues[num].removeById(id);
122
        val num = (id and EffectType.MASK.toLong()).toInt()
123
        return queues[num].removeById(id)
138 124
    }
139 125

  
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)
126
    ///////////////////////////////////////////////////////////////////////////////////////////////////
127
    /**
128
     * Aborts a single Effect.
129
     *
130
     * @param effect the Effect we want to abort.
131
     * @return number of Effects aborted. Always either 0 or 1.
132
     */
133
    fun abortEffect(effect: Effect): Int
148 134
    {
149
    int num = effect.getType().ordinal();
150
    return mQueues[num].removeEffect(effect);
135
        val num = effect.type.ordinal
136
        return queues[num].removeEffect(effect)
151 137
    }
152 138

  
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)
139
    ///////////////////////////////////////////////////////////////////////////////////////////////////
140
    /**
141
     * Abort all Effects of a given name, for example all rotations.
142
     *
143
     * @param name one of the constants defined in [EffectName]
144
     * @return number of Effects aborted.
145
     */
146
    fun abortByName(name: EffectName): Int
161 147
    {
162
    int num = name.getType().ordinal();
163
    return mQueues[num].removeByName(name);
148
        val num = name.type.ordinal
149
        return queues[num].removeByName(name)
164 150
    }
165 151

  
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)
152
    ///////////////////////////////////////////////////////////////////////////////////////////////////
153
    /**
154
     * Add a new Effect to the tail of our queue.
155
     *
156
     * @param effect The Effect to add.
157
     * @return `true` if operation was successful, `false` otherwise.
158
     */
159
    fun apply(effect: Effect): Boolean
174 160
    {
175
    int num = effect.getType().ordinal();
176
    return mQueues[num].add(effect);
161
        val num = effect.type.ordinal
162
        return queues[num].add(effect)
177 163
    }
178 164

  
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)
165
    ///////////////////////////////////////////////////////////////////////////////////////////////////
166
    /**
167
     * Add a new Effect to our queue at a specified position.
168
     *
169
     * @param effect The Effect to add.
170
     * @param position the place in the effects queue where to add the new effect.
171
     * @return `true` if operation was successful, `false` otherwise.
172
     */
173
    fun apply(effect: Effect, position: Int): Boolean
188 174
    {
189
    int num = effect.getType().ordinal();
190
    return mQueues[num].add(effect,position);
175
        val num = effect.type.ordinal
176
        return queues[num].add(effect, position)
191 177
    }
192 178

  
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
/**
195
 * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
196
 */
197
  public void markForDeletion()
179
    ///////////////////////////////////////////////////////////////////////////////////////////////////
180
    /**
181
     * Mark the underlying OpenGL object for deletion. Actual deletion will take place on the next render.
182
     */
183
    fun markForDeletion()
198 184
    {
199
    for( int i=0; i<EffectType.LENGTH; i++)
200
      {
201
      mQueues[i].markForDeletion();
202
      }
185
        for (i in 0 until EffectType.LENGTH)
186
        {
187
            queues[i].markForDeletion()
188
        }
203 189
    }
204 190

  
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)
191
    ///////////////////////////////////////////////////////////////////////////////////////////////////
192
    /**
193
     * Return number of effects of the given type currently in the Queue.
194
     *
195
     * @param type The EffectType.
196
     * @return Number of effects of the given type currently in the Queue.
197
     */
198
    fun getNumEffects(type: EffectType): Int
213 199
    {
214
    int num = type.ordinal();
215
    return mQueues[num].getNumEffects();
200
        val num = type.ordinal
201
        return queues[num].numEffects
216 202
    }
217 203

  
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219
/**
220
 * Return a string describing all effects in the queues.
221
 */
222
  public String debug(int depth)
204
    ///////////////////////////////////////////////////////////////////////////////////////////////////
205
    /**
206
     * Return a string describing all effects in the queues.
207
     */
208
    fun debug(depth: Int): String
223 209
    {
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;
210
        val s = StringBuilder()
211
        for (i in 0 until depth) s.append(" ")
212
        val space = s.toString()
213

  
214
        val mat = queues[0].retEffects()
215
        val ver = queues[1].retEffects()
216
        val fra = queues[2].retEffects()
217
        val pos = queues[3].retEffects()
218

  
219
        return """
220
         ${space}MAT: $mat
221
         ${space}VER: $ver
222
         ${space}FRA: $fra
223
         ${space}POS: $pos
224
         """.trimIndent()
234 225
    }
235
  }
226
}
src/main/java/org/distorted/library/main/DistortedFramebuffer.kt
17 17
// License along with this library; if not, write to the Free Software                           //
18 18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19 19
///////////////////////////////////////////////////////////////////////////////////////////////////
20
package org.distorted.library.main
20 21

  
21
package org.distorted.library.main;
22

  
23
import android.opengl.GLES30;
22
import android.opengl.GLES30
24 23

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

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

  
38
  public void create()
31
open class DistortedFramebuffer internal constructor(numfbos: Int, numcolors: Int, depthStencil: Int, type: Int, storage: Int, width: Int, height: Int) : InternalOutputSurface(width, height, NOT_CREATED_YET, numfbos, numcolors, depthStencil, NOT_CREATED_YET, type, storage)
32
{
33
    ///////////////////////////////////////////////////////////////////////////////////////////////////
34
    // Must be called from a thread holding OpenGL Context
35
    override fun create()
39 36
    {
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++)
37
        if( mNumFBOs==DistortedLibrary.WAIT_FOR_FBO_QUEUE_SIZE )
57 38
        {
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);
39
            // only now we know how many FBOs there should be
40
            mNumFBOs = DistortedLibrary.queueSize
41
            allocateColor()
42
            allocateStuffDependantOnNumFBOS()
72 43
        }
73 44

  
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++)
45
        //////////////////////////////////////////////////////////////
46
        // COLOR
47
        if( mColorCreated==NOT_CREATED_YET )
87 48
        {
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
          }
49
            GLES30.glGenTextures(mNumFBOs*mNumColors, mColorH, 0)
50
            GLES30.glGenFramebuffers(mNumFBOs, mFBOH, 0)
51

  
52
            for (i in 0 until mNumFBOs)
53
            {
54
                GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i])
55

  
56
                for (j in 0 until mNumColors)
57
                {
58
                    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mColorH!![i*mNumColors+j])
59
                    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT)
60
                    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT)
61
                    GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST.toFloat())
62
                    GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR.toFloat())
63
                    GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, mRealWidth, mRealHeight, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null)
64
                }
65

  
66
                GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, mColorH!![i*mNumColors], 0)
67
                GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
68
            }
69

  
70
            // TODO
71
            mColorCreated = checkStatus("color")
72
            GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
102 73
        }
103
      GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);
104 74

  
105
      for(int i=0; i<mNumFBOs; i++)
75
        //////////////////////////////////////////////////////////////
76
        // DEPTH / STENCIL
77
        if( mDepthStencilCreated==NOT_CREATED_YET )  // we need to create a new DEPTH or STENCIL attachment
106 78
        {
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
          }
79
            GLES30.glGenTextures(mNumFBOs, mDepthStencilH, 0)
80

  
81
            for (i in 0 until mNumFBOs)
82
            {
83
                GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mDepthStencilH!![i])
84
                GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT)
85
                GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT)
86
                GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
87
                GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST)
88

  
89
                if (mDepthStencil==DEPTH_NO_STENCIL)
90
                {
91
                    GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH_COMPONENT, mRealWidth, mRealHeight, 0, GLES30.GL_DEPTH_COMPONENT, GLES30.GL_UNSIGNED_INT, null)
92
                }
93
                else if (mDepthStencil==BOTH_DEPTH_STENCIL)
94
                {
95
                    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)
96
                }
97
            }
98
            GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0)
99

  
100
            for (i in 0 until mNumFBOs)
101
            {
102
                GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i])
103

  
104
                if (mDepthStencil==DEPTH_NO_STENCIL)
105
                {
106
                    GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, mDepthStencilH!![i], 0)
107
                }
108
                else if (mDepthStencil==BOTH_DEPTH_STENCIL)
109
                {
110
                    GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_STENCIL_ATTACHMENT, GLES30.GL_TEXTURE_2D, mDepthStencilH!![i], 0)
111
                }
112
            }
113

  
114
            // TODO
115
            mDepthStencilCreated = checkStatus("depth")
116
            GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
117 117
        }
118 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."
119
        //////////////////////////////////////////////////////////////
120
        // DETACH
133 121

  
134
      for(int i=0; i<mNumFBOs; i++)
122
        // TODO
123
        if( mDepthStencilCreated==DONT_CREATE && mDepthStencilH!![0]>0 )  // we need to detach and recreate the DEPTH attachment.
135 124
        {
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;
125
            // OpenGL ES 3.0.5 spec, chapter 4.4.2.4 :
126
            // "Note that the texture image is specifically not detached from any other framebuffer objects.
127
            //  Detaching the texture image from any other framebuffer objects is the responsibility of the application."
128

  
129
            for (i in 0 until mNumFBOs)
130
            {
131
                GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, mFBOH[i])
132
                GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, 0, 0)
133
                GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_STENCIL_ATTACHMENT, GLES30.GL_TEXTURE_2D, 0, 0)
134
                mDepthStencilH!![i] = 0
135
            }
136

  
137
            GLES30.glDeleteTextures(mNumFBOs, mDepthStencilH, 0)
138
            GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0)
140 139
        }
141

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

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

  
150
  private int checkStatus(String message)
142
    ///////////////////////////////////////////////////////////////////////////////////////////////////
143
    // TODO
144
    private fun checkStatus(message: String): Int
151 145
    {
152
    int status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER);
146
        val status = GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER)
153 147

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

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

  
163
      return FAILED_TO_CREATE;
164
      }
157
            return FAILED_TO_CREATE
158
        }
165 159

  
166
    return CREATED;
160
        return CREATED
167 161
    }
168 162

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

  
172
  public void delete()
163
    ///////////////////////////////////////////////////////////////////////////////////////////////////
164
    // Must be called from a thread holding OpenGL Context
165
    override fun delete()
173 166
    {
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
    }
167
        val colorH = mColorH!!
200 168

  
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
    }
169
        if( colorH[0]>0 )
170
        {
171
            GLES30.glDeleteTextures(mNumFBOs*mNumColors, colorH, 0)
172
            mColorCreated = NOT_CREATED_YET
173
            for (i in 0 until mNumFBOs*mNumColors) colorH[i] = 0
174
        }
221 175

  
222
///////////////////////////////////////////////////////////////////////////////////////////////////
176
        val depthStencilH = mDepthStencilH!!
223 177

  
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
    }
178
        if( depthStencilH[0]>0 )
179
        {
180
            GLES30.glDeleteTextures(mNumFBOs, depthStencilH, 0)
181
            mDepthStencilCreated = NOT_CREATED_YET
182
            for (i in 0 until mNumFBOs) depthStencilH[i] = 0
183
        }
235 184

  
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237
// create a multi-framebuffer (1 object containing multiple FBOs)
185
        if( mNumFBOs>0 && mFBOH[0]>0 )
186
        {
187
            GLES30.glDeleteFramebuffers(mNumFBOs, mFBOH, 0)
188
        }
238 189

  
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();
190
        for (i in 0 until mNumFBOs)
191
        {
192
            mFBOH[i] = 0
193
        }
243 194
    }
244 195

  
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)
196
    ///////////////////////////////////////////////////////////////////////////////////////////////////
197
    // called from onDestroy(); mark OpenGL assets as 'not created'
198
    override fun recreate()
252 199
    {
253
    this(1,numcolors,depthStencil,type,STORAGE_PRIVATE,width,height);
200
        if (mColorCreated!=DONT_CREATE)
201
        {
202
            mColorCreated = NOT_CREATED_YET
203
            mColorH!![0] = 0
204
        }
205
        if (mDepthStencilCreated!=DONT_CREATE)
206
        {
207
            mDepthStencilCreated = NOT_CREATED_YET
208
            mDepthStencilH!![0] = 0
209
        }
210
        for (i in 0 until mNumFBOs)
211
        {
212
            mFBOH[i] = 0
213
        }
254 214
    }
255 215

  
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)
216
    ///////////////////////////////////////////////////////////////////////////////////////////////////
217
    fun setAsInput(fbo: Int, texture: Int): Boolean
270 218
    {
271
    this(1,numcolors,depthStencil,TYPE_USER,STORAGE_PRIVATE,width,height);
272
    }
219
        if( (texture in 0..<mNumColors) && (fbo in 0..<mNumFBOs) )
220
        {
221
            val colorH = mColorH!![mNumColors*fbo+texture]
222

  
223
            if( colorH>0 )
224
            {
225
                GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
226
                GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, colorH)
227
                return true
228
            }
229
        }
273 230

  
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;
231
        return false
291 232
    }
292 233

  
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)
234
    ///////////////////////////////////////////////////////////////////////////////////////////////////
235
    // create a multi-framebuffer (1 object containing multiple FBOs)
236
    init
300 237
    {
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
      }
238
        markForCreation()
305 239
    }
306 240

  
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)
241
    ///////////////////////////////////////////////////////////////////////////////////////////////////
242
    // create SYSTEM or TREE framebuffers (those are just like normal FBOs, just hold information
243
    // that they were autocreated only for the Library's internal purposes (SYSTEM) or for using
244
    // inside a Tree of DistortedNodes (TREE)
245
    // SYSTEM surfaces do not get removed in onDestroy().
246
    internal constructor(numcolors: Int, depthStencil: Int, type: Int, width: Int, height: Int)
247
             : this(1, numcolors, depthStencil, type, STORAGE_PRIVATE, width, height)
248

  
249
    ///////////////////////////////////////////////////////////////////////////////////////////////////
250
    // PUBLIC API
251
    ///////////////////////////////////////////////////////////////////////////////////////////////////
252
    /**
253
     * Create new offscreen Framebuffer with configurable number of COLOR, DEPTH and STENCIL attachments.
254
     *
255
     * @param width        Width of all the COLOR attachments.
256
     * @param height       Height of all the COLOR attachments.
257
     * @param numcolors    How many COLOR attachments to create?
258
     * @param depthStencil Add DEPTH or STENCIL attachment?
259
     * Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
260
     */
261
    @Suppress("unused")
262
    constructor(width: Int, height: Int, numcolors: Int, depthStencil: Int)
263
      : this(1, numcolors, depthStencil, TYPE_USER, STORAGE_PRIVATE, width, height)
264

  
265
    ///////////////////////////////////////////////////////////////////////////////////////////////////
266
    /**
267
     * Bind the underlying rectangle of pixels as a OpenGL Texture.
268
     *
269
     * @param texture The Texture number to bind (and thus read from).
270
     * @return `true` if successful.
271
     */
272
    fun setAsInput(texture: Int): Boolean
314 273
    {
315
    if( depthStencil != mDepthStencil )
316
      {
317
      mDepthStencil = depthStencil;
318

  
319
      if( depthStencil!= NO_DEPTH_NO_STENCIL && mDepthStencilCreated==DONT_CREATE )
274
        if( texture in 0..<mNumColors )
320 275
        {
321
        mDepthStencilCreated = NOT_CREATED_YET;
322
        markForCreation();
276
            val colorH = mColorH!![2*mCurrFBO + texture]
277

  
278
            if( colorH>0 )
279
            {
280
                GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
281
                GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, colorH)
282
                return true
283
            }
323 284
        }
324
      if( depthStencil== NO_DEPTH_NO_STENCIL && mDepthStencilCreated!=DONT_CREATE )
285

  
286
        return false
287
    }
288

  
289
    ///////////////////////////////////////////////////////////////////////////////////////////////////
290
    /**
291
     * Attach the texture'th Texture to COLOR0 attachment.
292
     *
293
     * @param texture The Texture number to attach (and subsequently use to render to)
294
     */
295
    fun bindForOutput(texture: Int)
296
    {
297
        if( texture in 0..<mNumColors )
325 298
        {
326
        mDepthStencilCreated = DONT_CREATE;
327
        markForCreation();
299
            val colorH = mColorH!![2*mCurrFBO + texture]
300

  
301
            if( colorH>0 )
302
                GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, colorH, 0)
328 303
        }
329
      }
330 304
    }
331 305

  
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()
306
    ///////////////////////////////////////////////////////////////////////////////////////////////////
307
    /**
308
     * Enable/disable DEPTH and STENCIL buffers.
309
     *
310
     * @param depthStencil Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
311
     */
312
    fun enableDepthStencil(depthStencil: Int)
344 313
    {
345
    return mColorH[0];
314
        if( depthStencil!=mDepthStencil )
315
        {
316
            mDepthStencil = depthStencil
317

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

  
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)
331
    ///////////////////////////////////////////////////////////////////////////////////////////////////
332
    /**
333
     * Return the ID of the Texture (COLOR attachment 0) that's backing this FBO.
334
     *
335
     * Catch: this will only work if the library has had time to actually create the texture. Remember
336
     * that the texture gets created only on first render, thus creating a Texture object and immediately
337
     * calling this method will return an invalid (negative) result.
338
     *
339
     * @return If there was not a single render between creation of the Object and calling this method on
340
     * it, return a negative value. Otherwise, return ID of COLOR attachment 0.
341
     */
342
    val textureID: Int get() = mColorH!![0]
343

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

  
364
    return false;
360
        return false
365 361
    }
366
  }
362
}
src/main/java/org/distorted/library/main/DistortedLibrary.kt
17 17
// License along with this library; if not, write to the Free Software                           //
18 18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19 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;
20
package org.distorted.library.main
21

  
22
import android.opengl.GLES30
23
import android.opengl.GLES31
24
import org.distorted.library.R
25
import org.distorted.library.effect.Effect
26
import org.distorted.library.effect.EffectType
27
import org.distorted.library.effect.FragmentEffect
28
import org.distorted.library.effect.PostprocessEffect.Companion.createPrograms
29
import org.distorted.library.effect.VertexEffect
30
import org.distorted.library.effect.VertexEffect.Companion.allEnabled
31
import org.distorted.library.effect.VertexEffect.Companion.allGLSL
32
import org.distorted.library.effectqueue.EffectQueue
33
import org.distorted.library.effectqueue.EffectQueue.Companion.compute
34
import org.distorted.library.effectqueue.EffectQueue.Companion.getMax
35
import org.distorted.library.effectqueue.EffectQueue.Companion.send
36
import org.distorted.library.effectqueue.EffectQueue.Companion.setMax
37
import org.distorted.library.effectqueue.EffectQueuePostprocess.Companion.createPrograms
38
import org.distorted.library.effectqueue.EffectQueueVertex
39
import org.distorted.library.main.InternalRenderState.Companion.restoreDrawing
40
import org.distorted.library.main.InternalRenderState.Companion.switchOffDrawing
41
import org.distorted.library.main.InternalStackFrameList.isInitialized
42
import org.distorted.library.mesh.DeferredJobs
43
import org.distorted.library.mesh.MeshBase
44
import org.distorted.library.mesh.MeshBase.Companion.maxEffComponents
45
import org.distorted.library.mesh.MeshBase.Companion.useCenters
46
import org.distorted.library.message.EffectMessageSender.Companion.startSending
47
import org.distorted.library.program.DistortedProgram
48
import org.distorted.library.program.VertexCompilationException
49
import org.distorted.library.type.Dynamic
50
import java.io.InputStream
51
import java.nio.ByteBuffer
52
import java.nio.ByteOrder
53
import java.nio.FloatBuffer
54
import java.util.regex.Pattern
49 55

  
50 56
///////////////////////////////////////////////////////////////////////////////////////////////////
51 57
/**
52
 * A singleton class used to control various global dialog_settings.
58
 * A singleton class used to control various global settings.
53 59
 */
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
60
object DistortedLibrary
61
{
62
    /**
63
     * When creating an instance of a DistortedTexture from another instance, clone the Bitmap that's
64
     * backing up our DistortedTexture.
65
     *
66
     * This way we can have two DistortedTextures, both backed up by the same Bitmap, to which we can
67
     * apply different effects. Used in the copy constructor.
68
     */
69
    const val CLONE_SURFACE: Int = 0x1
70

  
71
    /**
72
     * When creating an instance of a DistortedEffects from another instance, clone the Matrix Effects.
73
     *
74
     * This way we can have two different DistortedEffects sharing the MATRIX queue.
75
     */
76
    const val CLONE_MATRIX: Int = 0x2
77

  
78
    /**
79
     * When creating an instance of a DistortedEffects from another instance, clone the Vertex Effects.
80
     *
81
     * This way we can have two different DistortedEffects sharing the VERTEX queue.
82
     */
83
    const val CLONE_VERTEX: Int = 0x4
84

  
85
    /**
86
     * When creating an instance of a DistortedEffects from another instance, clone the Fragment Effects.
87
     *
88
     * This way we can have two different DistortedEffects sharing the FRAGMENT queue.
89
     */
90
    const val CLONE_FRAGMENT: Int = 0x8
91

  
92
    /**
93
     * When creating an instance of a DistortedEffects from another instance, clone the PostProcess Effects.
94
     *
95
     * This way we can have two different DistortedEffects sharing the POSTPROCESS queue.
96
     */
97
    const val CLONE_POSTPROCESS: Int = 0x10
98

  
99
    /**
100
     * When creating an instance of a DistortedNode from another instance, clone the children Nodes.
101
     *
102
     * This is mainly useful for creating many similar sub-trees and rendering then at different places
103
     * on the screen with (optionally) different Effects.
104
     */
105
    const val CLONE_CHILDREN: Int = 0x20
106

  
107
    /**
108
     * When creating a DistortedScreen (which needs to have mFBOQueueSize FBOs attached), pass this
109
     * constant for 'numOfFBOs' and the number of backing FBOs will be taken from 'mFBOQueueSize'
110
     * (the value of which is most likely unknown at the time of creation of the Screen)
111
     */
112
    const val WAIT_FOR_FBO_QUEUE_SIZE: Int = -1
113
    ///////////////////////////////////////////////////////////////////////////////////////////////////
114
    /**
115
     * Work around bugs in ARM Mali driver by, instead to a single FBO, rendering to a circular queue
116
     * of mFBOQueueSize FBOs. (otherwise we sometimes get a 'full pipeline flush' and the end result
117
     * might be missing part of the Objects)
118
     *
119
     * This bug only exists on Mali driver r12. (or more precisely it's there in r12 but fixed in r22)
120
     *
121
     * [...](https://community.arm.com/graphics/f/discussions/10285/opengl-es-3-1-on-mali-t880-flashes)
122
     */
123
    var queueSize: Int = 0
124
        private set
125

  
126
    /**
127
     * Return OpenGL ES version supported by the hardware we are running on.
128
     * There are only three possibilities: 300 (OpenGL ES 3.0) or 310 (at least OpenGL ES 3.1)
129
     * or 200 (OpenGL ES 2.0)
130
     */
131
    @JvmStatic var gLSL: Int = 0
132
        private set
133
    private var mGLSL_VERSION: String? = null
134
    private var mOITCompilationAttempted = false
135
    private var mNeedsTransformFeedback = false
136

  
137
    /**
138
     * Return the maximum size of the texture supported by the driver.
139
     */
140
    @JvmStatic var maxTextureSize: Int = Int.MAX_VALUE
141
        private set
142

  
143
    /**
144
     * Return an interger - max number of uniforms one can upload to a Vertex Shader.
145
     */
146
    var maxVertexUniforms: Int = Int.MAX_VALUE
147
        private set
148

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

Also available in: Unified diff