Revision f4d6114c
Added by Leszek Koltunski over 6 years ago
src/main/java/org/distorted/library/effect/PostprocessEffect.java | ||
---|---|---|
139 | 139 |
* |
140 | 140 |
* @y.exclude |
141 | 141 |
*/ |
142 |
public abstract int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers); |
|
142 |
public abstract int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers, int fbo);
|
|
143 | 143 |
|
144 | 144 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
145 | 145 |
/** |
src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java | ||
---|---|---|
140 | 140 |
* |
141 | 141 |
* @y.exclude |
142 | 142 |
*/ |
143 |
public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers) |
|
143 |
public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers, int fbo)
|
|
144 | 144 |
{ |
145 | 145 |
if( mProgram1 ==null) |
146 | 146 |
{ |
... | ... | |
159 | 159 |
|
160 | 160 |
DistortedFramebuffer buffer = (DistortedFramebuffer)buffers[mQualityLevel]; |
161 | 161 |
|
162 |
buffer.setAsOutput();
|
|
162 |
buffer.setAsOutputFBO(fbo);
|
|
163 | 163 |
|
164 | 164 |
float w= buffer.getWidth(); |
165 | 165 |
float h= buffer.getHeight(); |
... | ... | |
182 | 182 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW; |
183 | 183 |
|
184 | 184 |
mProgram1.useProgram(); |
185 |
buffer.bindForOutput(1); |
|
186 |
buffer.setAsInput(0);
|
|
185 |
buffer.bindForOutput(2*fbo+1);
|
|
186 |
buffer.setAsInput(2*fbo);
|
|
187 | 187 |
|
188 | 188 |
GLES31.glColorMask(true,true,true,true); |
189 | 189 |
GLES31.glClearColor(1.0f,1.0f,1.0f,0.0f); |
... | ... | |
203 | 203 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH; |
204 | 204 |
|
205 | 205 |
mProgram2.useProgram(); |
206 |
buffer.bindForOutput(0);
|
|
207 |
buffer.setAsInput(1); |
|
206 |
buffer.bindForOutput(2*fbo);
|
|
207 |
buffer.setAsInput(2*fbo+1);
|
|
208 | 208 |
|
209 | 209 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT); |
210 | 210 |
|
src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java | ||
---|---|---|
144 | 144 |
* |
145 | 145 |
* @y.exclude |
146 | 146 |
*/ |
147 |
public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers) |
|
147 |
public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers, int fbo)
|
|
148 | 148 |
{ |
149 | 149 |
if( mProgram1 ==null) |
150 | 150 |
{ |
... | ... | |
180 | 180 |
int offset = radius + radius*radius/4; |
181 | 181 |
radius = (radius+1)/2; |
182 | 182 |
|
183 |
outBuffer.setAsOutput();
|
|
183 |
outBuffer.setAsOutputFBO(fbo);
|
|
184 | 184 |
GLES31.glViewport(0, 0, (int)w, (int)h); |
185 | 185 |
|
186 | 186 |
// horizontal glow |
187 | 187 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW; |
188 | 188 |
|
189 | 189 |
mProgram1.useProgram(); |
190 |
outBuffer.bindForOutput(1); |
|
191 |
inBuffer.setAsInput(0);
|
|
190 |
outBuffer.bindForOutput(2*fbo+1);
|
|
191 |
inBuffer.setAsInput(2*fbo);
|
|
192 | 192 |
|
193 | 193 |
GLES31.glColorMask(true,true,true,true); |
194 | 194 |
GLES31.glClearColor(1.0f,1.0f,1.0f,0.0f); |
... | ... | |
209 | 209 |
for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH; |
210 | 210 |
|
211 | 211 |
mProgram2.useProgram(); |
212 |
outBuffer.bindForOutput(0);
|
|
213 |
outBuffer.setAsInput(1); |
|
212 |
outBuffer.bindForOutput(2*fbo);
|
|
213 |
outBuffer.setAsInput(2*fbo+1);
|
|
214 | 214 |
|
215 | 215 |
GLES31.glUniform1f ( mProgram2.mUniform[0] , n ); |
216 | 216 |
GLES31.glUniform2f ( mProgram2.mUniform[1] , corrW, corrH ); |
src/main/java/org/distorted/library/main/Distorted.java | ||
---|---|---|
77 | 77 |
*/ |
78 | 78 |
public static final int CLONE_CHILDREN= 0x20; |
79 | 79 |
|
80 |
/** |
|
81 |
* Work around bugs in ARM Mali driver by, instead to a single FBO, rendering to a circular queue |
|
82 |
* of FBO_QUEUE_SIZE FBOs. (otherwise we sometimes get a 'full pipeline flush' and the end result |
|
83 |
* might be missing part of the Objects) |
|
84 |
*/ |
|
85 |
public static final int FBO_QUEUE_SIZE = 4; |
|
86 |
|
|
80 | 87 |
private static boolean mInitialized=false; |
81 | 88 |
|
82 | 89 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/library/main/DistortedFramebuffer.java | ||
---|---|---|
276 | 276 |
*/ |
277 | 277 |
public boolean setAsInput(int texture) |
278 | 278 |
{ |
279 |
if( texture>=0 && texture<mNumColors && mColorH[texture]>0 ) |
|
279 |
if( texture>=0 && texture<mNumFBOs*mNumColors && mColorH[texture]>0 )
|
|
280 | 280 |
{ |
281 | 281 |
GLES31.glActiveTexture(GLES31.GL_TEXTURE0); |
282 | 282 |
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, mColorH[texture]); |
... | ... | |
290 | 290 |
|
291 | 291 |
public void bindForOutput(int texture) |
292 | 292 |
{ |
293 |
if( texture>=0 && texture<mNumColors && mColorH[texture]>0 ) |
|
293 |
if( texture>=0 && texture<mNumFBOs*mNumColors && mColorH[texture]>0 )
|
|
294 | 294 |
{ |
295 | 295 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mColorH[texture], 0); |
296 | 296 |
} |
src/main/java/org/distorted/library/main/DistortedNode.java | ||
---|---|---|
264 | 264 |
|
265 | 265 |
if( input.setAsInput() ) |
266 | 266 |
{ |
267 |
surface.setAsOutput(); |
|
268 | 267 |
DistortedRenderState.setUpStencilMark(); |
269 | 268 |
mEffects.drawPriv(mSurface.getWidth() /2.0f, mSurface.getHeight()/2.0f, mMesh, surface, currTime, queue.getHalo()*surface.mMipmap); |
270 | 269 |
DistortedRenderState.unsetUpStencilMark(); |
src/main/java/org/distorted/library/main/DistortedOutputSurface.java | ||
---|---|---|
180 | 180 |
|
181 | 181 |
for(int j=0; j<EffectQuality.LENGTH; j++) |
182 | 182 |
{ |
183 |
mBuffer[j] = new DistortedFramebuffer(2,BOTH_DEPTH_STENCIL,TYPE_SYST, (int)(width*mipmap), (int)(height*mipmap) ); |
|
183 |
mBuffer[j] = new DistortedFramebuffer(Distorted.FBO_QUEUE_SIZE,2,BOTH_DEPTH_STENCIL,TYPE_SYST, (int)(width*mipmap), (int)(height*mipmap) );
|
|
184 | 184 |
mBuffer[j].mMipmap = mipmap; |
185 | 185 |
mBuffer[j].mNear = near; // copy mNear as well (for blitting- see PostprocessEffect.apply() ) |
186 | 186 |
mBuffer[j].glClearColor(1.0f,1.0f,1.0f,0.0f); |
... | ... | |
199 | 199 |
|
200 | 200 |
for(int j=0; j<EffectQuality.LENGTH; j++) |
201 | 201 |
{ |
202 |
mBuffer[j].setAsOutput(); |
|
203 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[1], 0); |
|
204 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT|GLES31.GL_DEPTH_BUFFER_BIT|GLES31.GL_STENCIL_BUFFER_BIT); |
|
205 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[0], 0); |
|
206 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT); |
|
202 |
for(int k=0; k<Distorted.FBO_QUEUE_SIZE; k++) |
|
203 |
{ |
|
204 |
GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mBuffer[j].mFBOH[k]); |
|
205 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[2*k+1], 0); |
|
206 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT | GLES31.GL_DEPTH_BUFFER_BIT | GLES31.GL_STENCIL_BUFFER_BIT); |
|
207 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[2*k ], 0); |
|
208 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT); |
|
209 |
} |
|
207 | 210 |
} |
211 |
|
|
212 |
GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, 0); |
|
208 | 213 |
} |
209 | 214 |
|
210 | 215 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
267 | 272 |
private int blitWithDepth(long currTime, DistortedOutputSurface buffer,int fbo) |
268 | 273 |
{ |
269 | 274 |
GLES31.glViewport(0, 0, mWidth, mHeight); |
270 |
setAsOutput(currTime,fbo); |
|
275 |
setAsOutputFBO(currTime,fbo);
|
|
271 | 276 |
GLES31.glActiveTexture(GLES31.GL_TEXTURE0); |
272 |
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, buffer.mColorH[0]);
|
|
277 |
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, buffer.mColorH[2*fbo]);
|
|
273 | 278 |
GLES31.glActiveTexture(GLES31.GL_TEXTURE1); |
274 |
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, buffer.mDepthStencilH[0]);
|
|
279 |
GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, buffer.mDepthStencilH[fbo]);
|
|
275 | 280 |
|
276 | 281 |
GLES31.glDisable(GLES31.GL_STENCIL_TEST); |
277 | 282 |
GLES31.glStencilMask(0x00); |
... | ... | |
290 | 295 |
GLES31.glClearDepthf(1.0f); |
291 | 296 |
GLES31.glClearStencil(0); |
292 | 297 |
|
293 |
buffer.setAsOutput();
|
|
294 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[1], 0); |
|
298 |
buffer.setAsOutputFBO(fbo);
|
|
299 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[2*fbo+1], 0);
|
|
295 | 300 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT|GLES31.GL_DEPTH_BUFFER_BIT|GLES31.GL_STENCIL_BUFFER_BIT); |
296 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[0], 0);
|
|
301 |
GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[2*fbo ], 0);
|
|
297 | 302 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT); |
298 | 303 |
|
299 | 304 |
return 1; |
... | ... | |
331 | 336 |
|
332 | 337 |
if( currBucket==0 ) |
333 | 338 |
{ |
334 |
setAsOutput(time,fbo); |
|
339 |
setAsOutputFBO(time,fbo);
|
|
335 | 340 |
numRenders += child1.draw(time,this); |
336 | 341 |
} |
337 | 342 |
else |
... | ... | |
349 | 354 |
for(int j=bucketChange; j<i; j++) |
350 | 355 |
{ |
351 | 356 |
child2 = children.get(j); |
357 |
mBuffer[internalQuality].setAsOutputFBO(fbo); |
|
352 | 358 |
numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality],lastQueue); |
353 | 359 |
} |
354 | 360 |
|
355 |
numRenders += lastQueue.postprocess(mBuffer); |
|
361 |
numRenders += lastQueue.postprocess(mBuffer,fbo);
|
|
356 | 362 |
numRenders += blitWithDepth(time, mBuffer[quality],fbo); |
357 | 363 |
|
358 |
mBuffer[quality].setAsOutputAndClear(time); |
|
364 |
mBuffer[quality].setAsOutputAndClear(time,fbo);
|
|
359 | 365 |
} |
360 | 366 |
|
361 | 367 |
internalQuality = currQueue.getInternalQuality(); |
... | ... | |
363 | 369 |
bucketChange = i; |
364 | 370 |
} |
365 | 371 |
|
366 |
mBuffer[quality].setAsOutput(time);
|
|
372 |
mBuffer[quality].setAsOutputFBO(time,fbo);
|
|
367 | 373 |
child1.drawNoBlend(time,mBuffer[quality]); |
368 | 374 |
|
369 | 375 |
if( i==numChildren-1 ) |
... | ... | |
371 | 377 |
for(int j=bucketChange; j<numChildren; j++) |
372 | 378 |
{ |
373 | 379 |
child2 = children.get(j); |
380 |
mBuffer[internalQuality].setAsOutputFBO(fbo); |
|
374 | 381 |
numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality],currQueue); |
375 | 382 |
} |
376 | 383 |
|
377 |
numRenders += currQueue.postprocess(mBuffer); |
|
384 |
numRenders += currQueue.postprocess(mBuffer,fbo);
|
|
378 | 385 |
numRenders += blitWithDepth(time, mBuffer[quality],fbo); |
379 | 386 |
} |
380 | 387 |
} // end postprocessed child case |
... | ... | |
422 | 429 |
* Useful for drawing to the postprocessing buffer, which must sometimes be cleared multiple times |
423 | 430 |
* per frame. |
424 | 431 |
*/ |
425 |
|
|
426 |
private void setAsOutputAndClear(long time) |
|
432 |
private void setAsOutputAndClear(long time,int fbo) |
|
427 | 433 |
{ |
428 |
GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
|
|
434 |
GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[fbo]);
|
|
429 | 435 |
|
430 |
mTime[0] = time; // have to do this otherwise on the next setAsOutput() we would clear
|
|
436 |
mTime[fbo] = time; // have to do this otherwise on the next setAsOutput() we would clear
|
|
431 | 437 |
DistortedRenderState.colorDepthStencilOn(); |
432 | 438 |
GLES31.glClearColor(mClearR, mClearG, mClearB, mClearA); |
433 | 439 |
GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT); |
... | ... | |
436 | 442 |
|
437 | 443 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
438 | 444 |
|
439 |
private void setAsOutput(long time, int fbo) |
|
445 |
private void setAsOutputFBO(long time, int fbo)
|
|
440 | 446 |
{ |
441 | 447 |
if( fbo>=0 && fbo<mNumFBOs ) |
442 | 448 |
{ |
... | ... | |
450 | 456 |
} |
451 | 457 |
else |
452 | 458 |
{ |
453 |
android.util.Log.e("surface", "error in setAsOutput, fbo="+fbo); |
|
459 |
android.util.Log.e("surface", "error in setAsOutput1, fbo="+fbo); |
|
460 |
} |
|
461 |
} |
|
462 |
|
|
463 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
464 |
/** |
|
465 |
* Not part of the Public API. |
|
466 |
* |
|
467 |
* @y.exclude |
|
468 |
*/ |
|
469 |
public void setAsOutputFBO(int fbo) |
|
470 |
{ |
|
471 |
if( fbo>=0 && fbo<mNumFBOs ) |
|
472 |
{ |
|
473 |
GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[fbo]); |
|
474 |
} |
|
475 |
else |
|
476 |
{ |
|
477 |
android.util.Log.e("surface", "error in setAsOutput2, fbo="+fbo); |
|
454 | 478 |
} |
455 | 479 |
} |
456 | 480 |
|
src/main/java/org/distorted/library/main/DistortedScreen.java | ||
---|---|---|
56 | 56 |
///// END DEBUGGING ////////////////////////// |
57 | 57 |
|
58 | 58 |
private int mCurrFBO; |
59 |
private static final int NUM_FBO = 3; |
|
60 | 59 |
|
61 | 60 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
62 | 61 |
// PUBLIC API |
... | ... | |
68 | 67 |
*/ |
69 | 68 |
public DistortedScreen() |
70 | 69 |
{ |
71 |
super(NUM_FBO,1,BOTH_DEPTH_STENCIL, TYPE_SYST, 1,1);
|
|
70 |
super(Distorted.FBO_QUEUE_SIZE,1,BOTH_DEPTH_STENCIL, TYPE_SYST, 1,1);
|
|
72 | 71 |
mShowFPS = false; |
73 | 72 |
mCurrFBO = 0; |
74 | 73 |
} |
... | ... | |
122 | 121 |
} |
123 | 122 |
|
124 | 123 |
mCurrFBO++; |
125 |
if( mCurrFBO>=NUM_FBO ) mCurrFBO=0;
|
|
124 |
if( mCurrFBO>=Distorted.FBO_QUEUE_SIZE ) mCurrFBO=0;
|
|
126 | 125 |
|
127 | 126 |
return numrender+1; |
128 | 127 |
} |
src/main/java/org/distorted/library/main/EffectQueuePostprocess.java | ||
---|---|---|
100 | 100 |
|
101 | 101 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
102 | 102 |
|
103 |
int postprocess(DistortedOutputSurface[] buffers) |
|
103 |
int postprocess(DistortedOutputSurface[] buffers, int fbo)
|
|
104 | 104 |
{ |
105 | 105 |
int numRenders = 0; |
106 | 106 |
|
... | ... | |
108 | 108 |
|
109 | 109 |
for(int i=0; i<mNumEffects; i++) |
110 | 110 |
{ |
111 |
numRenders += ((PostprocessEffect)mEffects[i]).apply(mUniforms,NUM_UNIFORMS*i, buffers); |
|
111 |
numRenders += ((PostprocessEffect)mEffects[i]).apply(mUniforms,NUM_UNIFORMS*i, buffers, fbo);
|
|
112 | 112 |
} |
113 | 113 |
|
114 | 114 |
GLES31.glEnable(GLES31.GL_BLEND); |
Also available in: Unified diff
I spoke too soon, the ARM Mali flashing is of course not fixed yet. The previous commit fixed Triblur, but the bug is still reproducible elsewhere (only in the 'postprocessed' apps though).
This commit introduces a circular queue in case of the postprocessing FBOs - with little success though.