Project

General

Profile

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

library / src / main / java / org / distorted / library / main / DistortedFramebuffer.java @ c41d046c

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.library.main;
21

    
22
import android.opengl.GLES31;
23

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

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

    
37
  void create()
38
    {
39
    if( mColorCreated==NOT_CREATED_YET )
40
      {
41
      GLES31.glGenTextures( mNumColors, mColorH, 0);
42
      GLES31.glGenFramebuffers(1, mFBOH, 0);
43
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
44

    
45
      for(int i=0; i<mNumColors; i++)
46
        {
47
        GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, mColorH[i]);
48
        GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_WRAP_S, GLES31.GL_REPEAT);
49
        GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_WRAP_T, GLES31.GL_REPEAT);
50
        GLES31.glTexParameterf(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MIN_FILTER, GLES31.GL_NEAREST);
51
        GLES31.glTexParameterf(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_LINEAR);
52
        GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA, mRealWidth, mRealHeight, 0, GLES31.GL_RGBA, GLES31.GL_UNSIGNED_BYTE, null);
53
        }
54
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mColorH[0], 0);
55
      GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
56
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, 0);
57

    
58
      mColorCreated = checkStatus("color");
59
      }
60
    if( mDepthStencilCreated==NOT_CREATED_YET ) // we need to create a new DEPTH or STENCIL attachment
61
      {
62
      GLES31.glGenTextures(1, mDepthStencilH, 0);
63
      GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, mDepthStencilH[0]);
64
      GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_WRAP_S, GLES31.GL_REPEAT);
65
      GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_WRAP_T, GLES31.GL_REPEAT);
66
      GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MIN_FILTER, GLES31.GL_NEAREST);
67
      GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_NEAREST);
68
      GLES31.glTexParameteri(GLES31.GL_TEXTURE_2D, GLES31.GL_DEPTH_STENCIL_TEXTURE_MODE, GLES31.GL_DEPTH_COMPONENT);
69

    
70
      if( mDepthStencil==DEPTH_NO_STENCIL )
71
        {
72
        GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_DEPTH_COMPONENT, mRealWidth, mRealHeight, 0, GLES31.GL_DEPTH_COMPONENT, GLES31.GL_UNSIGNED_INT, null);
73
        }
74
      else if( mDepthStencil==BOTH_DEPTH_STENCIL )
75
        {
76
        GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_DEPTH24_STENCIL8, mRealWidth, mRealHeight, 0, GLES31.GL_DEPTH_STENCIL, GLES31.GL_UNSIGNED_INT_24_8, null);
77
        }
78

    
79
      GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
80
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
81

    
82
      if( mDepthStencil==DEPTH_NO_STENCIL )
83
        {
84
        GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_DEPTH_ATTACHMENT, GLES31.GL_TEXTURE_2D, mDepthStencilH[0], 0);
85
        }
86
      else if( mDepthStencil==BOTH_DEPTH_STENCIL )
87
        {
88
        GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_DEPTH_STENCIL_ATTACHMENT, GLES31.GL_TEXTURE_2D, mDepthStencilH[0], 0);
89
        }
90

    
91
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, 0);
92

    
93
      mDepthStencilCreated = checkStatus("depth");
94
      }
95
    if( mDepthStencilCreated==DONT_CREATE && mDepthStencilH[0]>0 ) // we need to detach and recreate the DEPTH attachment.
96
      {
97
      // OpenGL ES 3.0.5 spec, chapter 4.4.2.4 :
98
      // "Note that the texture image is specifically not detached from any other framebuffer objects.
99
      //  Detaching the texture image from any other framebuffer objects is the responsibility of the application."
100
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
101
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_DEPTH_ATTACHMENT        , GLES31.GL_TEXTURE_2D, 0, 0);
102
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_DEPTH_STENCIL_ATTACHMENT, GLES31.GL_TEXTURE_2D, 0, 0);
103
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, 0);
104

    
105
      GLES31.glDeleteTextures(1, mDepthStencilH, 0);
106
      mDepthStencilH[0]=0;
107
      }
108
    }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

    
112
  private int checkStatus(String message)
113
    {
114
    int status = GLES31.glCheckFramebufferStatus(GLES31.GL_FRAMEBUFFER);
115

    
116
    if(status != GLES31.GL_FRAMEBUFFER_COMPLETE)
117
      {
118
      android.util.Log.e("DistortedFramebuffer", "FRAMEBUFFER INCOMPLETE, "+message+" error="+status);
119

    
120
      GLES31.glDeleteTextures(1, mColorH, 0);
121
      GLES31.glDeleteTextures(1, mDepthStencilH, 0);
122
      GLES31.glDeleteFramebuffers(1, mFBOH, 0);
123
      mFBOH[0]= 0;
124

    
125
      return FAILED_TO_CREATE;
126
      }
127

    
128
    return CREATED;
129
    }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132
// Must be called from a thread holding OpenGL Context
133

    
134
  void delete()
135
    {
136
    if( mColorH[0]>0 )
137
      {
138
      GLES31.glDeleteTextures(1, mColorH, 0);
139
      mColorH[0] = 0;
140
      mColorCreated = NOT_CREATED_YET;
141
      }
142

    
143
    if( mDepthStencilH[0]>0 )
144
      {
145
      GLES31.glDeleteTextures(1, mDepthStencilH, 0);
146
      mDepthStencilH[0]=0;
147
      mDepthStencilCreated = NOT_CREATED_YET;
148
      }
149

    
150
    GLES31.glDeleteFramebuffers(1, mFBOH, 0);
151
    mFBOH[0] = 0;
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155
// called from onDestroy(); mark OpenGL assets as 'not created'
156

    
157
  void recreate()
158
    {
159
    if( mColorCreated!=DONT_CREATE )
160
      {
161
      mColorCreated = NOT_CREATED_YET;
162
      mColorH[0] = 0;
163
      }
164
    if( mDepthStencilCreated!=DONT_CREATE )
165
      {
166
      mDepthStencilCreated = NOT_CREATED_YET;
167
      mDepthStencilH[0] = 0;
168
      }
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
// create SYSTEM or TREE framebuffers (those are just like normal FBOs, just hold information
173
// that they were autocreated only for the Library's internal purposes (SYSTEM) or for using
174
// inside a Tree of DistortedNodes (TREE)
175
// SYSTEM surfaces do not get removed in onDestroy().
176

    
177
  DistortedFramebuffer(int numcolors, int depthStencil, int type, int width, int height)
178
    {
179
    super(width,height,NOT_CREATED_YET,numcolors,depthStencil,NOT_CREATED_YET, type);
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183
// PUBLIC API
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185
/**
186
 * Create new offscreen Framebuffer with configurable number of COLOR, DEPTH and STENCIL attachments.
187
 *
188
 * @param width        Width of all the COLOR attachments.
189
 * @param height       Height of all the COLOR attachments.
190
 * @param numcolors    How many COLOR attachments to create?
191
 * @param depthStencil Add DEPTH or STENCIL attachment?
192
 *                     Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
193
 */
194
  @SuppressWarnings("unused")
195
  public DistortedFramebuffer(int width, int height, int numcolors, int depthStencil)
196
    {
197
    super(width,height,NOT_CREATED_YET,numcolors,depthStencil,NOT_CREATED_YET,TYPE_USER);
198
    }
199

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

    
202
/**
203
 * Create new offscreen Framebuffer with COLOR0 attachment only.
204
 *
205
 * @param width Width of the COLOR0 attachment.
206
 * @param height Height of the COLOR0 attachment.
207
 */
208
  @SuppressWarnings("unused")
209
  public DistortedFramebuffer(int width, int height)
210
    {
211
    super(width,height,NOT_CREATED_YET, 1, NO_DEPTH_NO_STENCIL,NOT_CREATED_YET,TYPE_USER);
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
/**
216
 * Bind the underlying rectangle of pixels as a OpenGL Texture.
217
 *
218
 * @return <code>true</code> if successful.
219
 */
220
  public boolean setAsInput()
221
    {
222
    if( mColorH[0]>0 )
223
      {
224
      GLES31.glActiveTexture(GLES31.GL_TEXTURE0);
225
      GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, mColorH[0]);
226
      return true;
227
      }
228

    
229
    return false;
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233
/**
234
 * Bind the underlying rectangle of pixels as a OpenGL Texture.
235
 *
236
 * @return <code>true</code> if successful.
237
 */
238
  public boolean setAsInput(int texture)
239
    {
240
    if( texture>=0 && texture<mNumColors && mColorH[texture]>0 )
241
      {
242
      GLES31.glActiveTexture(GLES31.GL_TEXTURE0);
243
      GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, mColorH[texture]);
244
      return true;
245
      }
246

    
247
    return false;
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  public void bindForOutput(int texture)
253
    {
254
    if( texture>=0 && texture<mNumColors && mColorH[texture]>0 )
255
      {
256
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mColorH[texture], 0);
257
      }
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261
/**
262
 * Enable.disable DEPTH and STENCIL buffers.
263
 *
264
 * @param depthStencil Valid values: NO_DEPTH_NO_STENCIL, DEPTH_NO_STENCIL, BOTH_DEPTH_STENCIL.
265
 */
266
  public void enableDepthStencil(int depthStencil)
267
    {
268
    if( depthStencil != mDepthStencil )
269
      {
270
      mDepthStencil = depthStencil;
271

    
272
      if( depthStencil!= NO_DEPTH_NO_STENCIL && mDepthStencilCreated==DONT_CREATE )
273
        {
274
        mDepthStencilCreated = NOT_CREATED_YET;
275
        markForCreation();
276
        }
277
      if( depthStencil== NO_DEPTH_NO_STENCIL && mDepthStencilCreated!=DONT_CREATE )
278
        {
279
        mDepthStencilCreated = DONT_CREATE;
280
        markForCreation();
281
        }
282
      }
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286
/**
287
 * Return the ID of the Texture (COLOR attachment 0) that's backing this FBO.
288
 * <p>
289
 * Catch: this will only work if the library has had time to actually create the texture. Remember
290
 * that the texture gets created only on first render, thus creating a Texture object and immediately
291
 * calling this method will return an invalid (negative) result.
292
 *
293
 * @return If there was not a single render between creation of the Object and calling this method on
294
 *         it, return a negative value. Otherwise, return ID of COLOR attachment 0.
295
 */
296
  public int getTextureID()
297
    {
298
    return mColorH[0];
299
    }
300
  }
(3-3/21)